Pergunta

Estou trabalhando em uma consulta para um site de notícias, que encontrará FeaturedContent para exibição na página inicial principal. O conteúdo marcado dessa forma é marcado como 'Conteúdo em destaque' e classificado em uma tabela de destaque por 'página inicial'. Atualmente, tenho a saída desejada, mas a consulta é executada em mais de 3 segundos, que preciso reduzir. Como otimizar uma consulta como a que segue?

EDITAR: materializou a visualização a cada minuto, conforme sugerido, até 0,4 segundos:

SELECT f.position, s.item_id, s.item_type, s.title, s.caption, s.date
FROM live.search_all s 
INNER JOIN live.tags t 
ON s.item_id = t.item_id AND s.item_type = t.item_type AND t.tag = 'FeaturedContent' 
LEFT OUTER JOIN live.featured f 
ON s.item_id = f.item_id AND s.item_type = f.item_type AND f.feature_type = 'homepage'
ORDER BY position IS NULL, position ASC, date

Isso retorna todos os recursos da página inicial em ordem, seguidos por outros conteúdos em destaque, classificados por data.
A explicação é parecida com esta:

|-id---|-select_type-|-table-|-type---|-possible_keys---------|-key--------|-key_len-|-ref---------------------------------------|-rows--|-Extra-------------------------------------------------------------|
|-1----|-SIMPLE------|-t2----|-ref----|-PRIMARY,tag_index-----|-tag_index--|-303-----|-const-------------------------------------|-2-----|-Using where; Using index; Using temporary; Using filesort;--------|
|-1----|-SIMPLE------|-t-----|-ref----|-PRIMARY---------------|-PRIMARY----|-4-------|-newswires.t2.id---------------------------|-1974--|-Using index-------------------------------------------------------|
|-1----|-SIMPLE------|-s-----|-eq_ref-|-PRIMARY, search_index-|-PRIMARY----|-124-----|-newswires.t.item_id,newswires.t.item_type-|-1-----|-------------------------------------------------------------------|
|-1----|-SIMPLE------|-f-----|-index--|-NULL------------------|-PRIMARY----|-190-----|-NULL--------------------------------------|-13----|-Using index-------------------------------------------------------|

E o perfil é o seguinte:

|-Status---------------|-Time-----|
|-starting-------------|-0.000091-|
|-Opening tables-------|-0.000756-|
|-System lock----------|-0.000005-|
|-Table lock-----------|-0.000008-|
|-init-----------------|-0.000004-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000043-|
|-optimizing-----------|-0.000019-|
|-statistics-----------|-0.000127-|
|-preparing------------|-0.000023-|
|-Creating tmp table---|-0.001802-|
|-executing------------|-0.000001-|
|-Copying to tmp table-|-0.311445-|
|-Sorting result-------|-0.014819-|
|-Sending data---------|-0.000227-|
|-end------------------|-0.000002-|
|-removing tmp table---|-0.002010-|
|-end------------------|-0.000005-|
|-query end------------|-0.000001-|
|-freeing items--------|-0.000296-|
|-logging slow query---|-0.000001-|
|-cleaning up----------|-0.000007-|

Sou novo na leitura do resultado do EXPLAIN, então não tenho certeza se tenho uma ordem melhor disponível ou algo bastante simples que possa ser feito para acelerar o processo.

A tabela search_all é a tabela de visão materializada que é atualizada periodicamente, enquanto as tags e tabelas apresentadas são visões. Essas visualizações não são opcionais e não podem ser contornadas.

A visualização de tags combina tags e uma tabela relacional para obter uma lista de tags de acordo com item_type e item_id, mas as outras visualizações são visualizações simples de uma tabela.

EDIT: Com a visão materializada, o maior gargalo parece ser a etapa 'Copiar para a mesa temporária' Sem ordenar a saída, leva 0,0025 segundos (muito melhor!), Mas a saída final precisa ser ordenada. Existe alguma maneira de melhorar o desempenho dessa etapa ou contorná-la?

Desculpe se a formatação for difícil de ler, sou novo e não tenho certeza de como ela é feita regularmente.
Obrigado pela ajuda! Se precisar de mais alguma coisa, entre em contato comigo!

EDITAR: Tamanhos de tabela, para referência:
Relações de tag: 197.411
Tags: 16.897
Histórias: 51.801
Imagens: 28.383
Vídeos: 2.408
Apresentado: 13

Foi útil?

Solução

Acho que otimizar sua consulta por si só não será muito útil. As primeiras reflexões são que ingressar em uma subconsulta, ela própria feita de UNIONs, é por si só um gargalo duplo para o desempenho.

Se você tiver a opção de alterar a estrutura do banco de dados, sugiro mesclar as 3 tabelas stories, images e videos em uma, se forem, como parecem, muito semelhantes (adicionando-lhes um type ENUM('story', 'image', 'video')) para diferenciar os registros; isso removeria a subconsulta e a união.

Além disso, parece que suas visualizações sobre stories e videos não estão usando um campo indexado para filtrar o conteúdo. Você está consultando uma coluna indexada?

É um problema bastante complicado sem saber a estrutura completa da tabela e a repartição dos seus dados!

Outra opção, que não envolveria trazer modificações para seu banco de dados existente (especialmente se já estiver em produção), seria "armazenar em cache" essas informações em outra tabela, que seria periodicamente atualizada por um cron job.

O armazenamento em cache pode ser feito em diferentes níveis, na consulta completa ou em suas subpartes (visualizações independentes ou as 3 uniões mescladas em uma única tabela de cache, etc.)

A viabilidade desta opção depende se é aceitável exibir dados ligeiramente desatualizados ou não. Pode ser aceitável apenas para algumas partes dos seus dados, o que pode implicar que você armazenará em cache apenas um subconjunto das tabelas / visualizações envolvidas na consulta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top