Aqui está uma pergunta que fiz ontem - https://stackoverflow.com/questions/22180727/left-joining-two-views-is-slow .
Recebi uma boa resposta que me ajudou, mas não entendo por que o LEFT JOIN é muito mais lento que a pesquisa. O LEFT JOIN durou 16 segundos - e tenho certeza de que minhas tabelas estão pelo menos 90% otimizadas - e ao fazer a pesquisa, são apenas 0,14 segundos. Quando eu LEFT JOIN tabelas, não é tão lento, então por que visualizações?
De acordo com a documentação do MySQL em visualizações
A primeira coisa que deve ser percebida sobre uma visão é que ela produz um conjunto de resultados. O conjunto de resultados que emerge da consulta invocada da exibição é uma tabela virtual porque é criada sob demanda. Não há DDL que você possa convocar posteriormente para indexar imediatamente o conjunto de resultados. Para todos os efeitos, o conjunto de resultados é uma tabela sem nenhum índice. Na verdade, o LEFT JOIN que você estava executando é basicamente um produto cartesiano com alguma filtragem.
Para dar uma visão mais granular do JOIN de duas visualizações, vou me referir a um post que fiz no ano passado explicando os mecanismos internos que o MySQL usa para avaliar JOINs e WHEREs ( Existe uma diferença de execução entre uma condição JOIN e uma condição WHERE? ). Mostrarei o mecanismo conforme publicado em Compreendendo o MySQL Internals (Página 172):
ORDER BY
eGROUP BY
.OK, parece que os índices devem ser usados. No entanto, olhe mais de perto. Se você substituir a palavra
View
porTable
, veja o que acontece com a execução do mecanismo:MECANISMO MODIFICADO
views
e escolha a melhor para cada umaview
.view
, decida se umaview
varredura é melhor do que a leitura de uma chave. Se houver muitos registros que correspondam ao valor da chave, as vantagens da chave serão reduzidas e aview
varredura se tornará mais rápida.views
deve ser unido quando mais de umviews
estiver presente na consulta.views
da junção.ORDER BY
eGROUP BY
.Cada tabela (visão) não possui índice. Assim, trabalhar com tabelas virtuais, tabelas temporárias ou tabelas sem índices torna-se realmente indistinto ao fazer um JOIN. As chaves usadas são apenas para operações JOIN, não tanto para procurar coisas mais rapidamente.
Pense em sua consulta como pegar duas listas telefônicas, as Páginas Amarelas de 2014 e as Páginas Amarelas de 2013. Cada livro das Páginas Amarelas contém as Páginas Brancas para Números de Telefone Residenciais.
Obviamente, existem diferenças entre as duas listas telefónicas. Fazer um JOIN de tabelas de banco de dados para descobrir as diferenças entre 2013 e 2014 não deve representar nenhum problema.
Imagine fundir as duas listas telefônicas manualmente para localizar as diferenças. Parece insano, não é? Não obstante, isso é exatamente o que você está pedindo ao mysqld para fazer quando você junta duas views. Lembre-se, você não está juntando tabelas reais e não há índices para pegar carona.
Agora, vamos olhar para trás na consulta real.
Você está usando uma tabela virtual (tabela sem índices), viewA, unindo-a a outra tabela virtual, viewB. A tabela temporária sendo gerada intermitentemente seria tão grande quanto viewA. Em seguida, você executa uma classificação interna na grande tabela temporária para torná-la distinta.
EPÍLOGO
Dados os mecanismos internos de avaliação de JOINs, juntamente com a natureza transitória e sem índice do conjunto de resultados de uma exibição, sua consulta original (LEFT JOIN de duas exibições) deve obter tempos de execução que são ordens de magnitude. Ao mesmo tempo, a resposta que você obteve do StackOverflow deve ter um bom desempenho, dado o mesmo algoritmo JOIN que acabei de descrever.
Espero que os detalhes sangrentos que acabei de postar respondam à sua pergunta sobre o porquê.
EXPLAIN EXTENDED [select query]
e, em seguidaSHOW WARNINGS
, mostrará a forma reescrita da exibição. A partir daqui, é mais fácil analisar as características de desempenho.As consultas de verificação visual geralmente não são fáceis de otimizar.
A resposta tem a ver com o método de realização de cada uma dessas operações.
Como as exibições são inerentemente não indexadas, as operações JOIN usando campos de exibições levarão mais tempo do que as operações JOIN usando tabelas, pois a varredura não pode usar um índice.
Nesse caso, a pesquisa também limita o número de registros que devem ser retornados no processamento - ela apenas extrai registros de uma visualização que não existem na outra. O JOIN extrai todos os registros e verifica se existem registros em ambos.