Depois de ler a consulta Slow SQL, não tenho certeza de como otimizar , isso me fez pensar no desempenho geral das consultas. Certamente, precisamos que os resultados da primeira tabela (quando outras tabelas são unidas) sejam tão pequenos quanto possível antes da junção (junções internas para esta questão) para tornar nossas consultas um pouco mais rápidas.
Exemplo, deve isso:
SELECT *
FROM ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2
Seja melhor/mais rápido do que:
SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val
Minha teoria é a seguinte (essa pode não ser a implementação correta, estou tentando lembrar de um livro interno do SQL Server 2008 que li (MSFT Press)):
- O processador de consultas primeiro obtém a tabela da esquerda (tabela1)
- Junta a segunda tabela (tabela2) e forma um produto cartesiano antes de filtrar as linhas necessárias (se aplicável)
- Em seguida, executa as cláusulas WHERE, ORDER BY, GROUP BY, HAVING com a instrução SEELCT por último.
Portanto, se na instrução nº 1 acima a tabela for menor, o mecanismo SQL terá menos trabalho a fazer ao formar os produtos cartesianos. Então, quando você alcança a instrução where, você tem um conjunto de resultados reduzido para filtrar na memória.
Eu poderia estar tão longe da realidade que é irreal. Como eu disse, é uma teoria.
Seus pensamentos?
Nota : Acabei de pensar nessa questão e ainda não tive a chance de executar nenhum teste.
Nota 2 : Marcado como SQL Server, pois não sei nada sobre a implementação do MySql etc. Sinta-se à vontade para responder/comentar de qualquer maneira
O processamento lógico de uma consulta está no MSDN (escrito pela equipe do Microsoft SQL Server, não por terceiros)
Uma tabela derivada segue isso, então a consulta externa faz isso novamente etc etc
Isso é lógico : não é real . Não importa como o SQL Server realmente faça isso, essas semânticas são honradas ao pé da letra . O "real" é determinado pelo Query Optimizer (QO) e você evita o produto intermediário Cartesion que você mencionou.
Vale a pena mencionar que o SQL é declarativo: você diz "o que" e não "como" como faria para uma programação procedural/imperativa (Java, .net). Portanto, dizer "isso acontece antes disso" é errado em muitos casos (por exemplo, suposição de curto-circuitos ou ordem L-para-R WHERE)
No seu caso acima, o QO irá gerar o mesmo plano independente de como ele está estruturado, pois é uma consulta simples.
No entanto, o QO é baseado em custo e para uma consulta complexa pode levar 2 semanas para gerar o plano ideal. Então ele faz "bom o suficiente", o que na verdade não é.
Portanto, seu primeiro caso pode ajudar o otimizador a encontrar um plano melhor porque a ordem de processamento lógico é diferente para as 2 consultas. Mas pode não.
Eu usei esse truque no SQL Server 2000 para obter uma melhoria de desempenho de velocidade de 60x em consultas de relatórios. À medida que o QO melhora de versão para versão, fica melhor em resolver essas coisas.
E o livro que você mencionou: há alguma disputa sobre isso
Veja SO e os links subsequentes: https://stackoverflow.com/q/3270338/27535
Uma consulta SQL não é de natureza processual, não há processamento de cima para baixo dos operadores de junção. A ordenação das tabelas em suas consultas de exemplo não tem influência no plano de execução, pois elas são logicamente equivalentes e gerarão exatamente o mesmo plano.
Você está avaliando duas das opções que o otimizador de consulta pode considerar ao gerar um plano para essa consulta. O principal fator que influencia a escolha do plano são as estatísticas das tabelas envolvidas e os custos associados às escolhas do operador em qualquer plano candidato.
Uma junção de duas tabelas muito simples, como o seu exemplo, pode ser satisfeita com qualquer uma das centenas de planos de execução diferentes. O otimizador decide qual será a melhor maneira de responder à sua consulta comparando os custos desses planos.
Às vezes, ele erra e você pode ajudá-lo a fazer melhores escolhas por meio de indexação aprimorada, mantendo as estatísticas atualizadas e aplicando dicas. Em casos muito raros, você pode querer forçar a ordem de execução usando a dica FORCE ORDER, mas isso deve ser usado com moderação. É um martelo para quebrar uma noz, o otimizador geralmente pode ser provocado para gerar melhores planos, alimentando-o com melhores informações.