Ordem de processamento de junção do SQL Server / where

18

Depois de ler a consulta SQL lenta, sem saber como otimizar , ele me fez pensar no desempenho geral das consultas. Certamente, precisamos que os resultados da primeira tabela (quando outras tabelas forem unidas) sejam os menores possíveis antes da união (junções internas para esta pergunta), a fim de tornar nossas consultas um pouco mais rápidas.

Exemplo, caso isso:

SELECT *
FROM   ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2

Seja melhor / mais rápido que:

SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val

Minha teoria é a seguinte (talvez essa não seja a implementação correta, estou tentando me lembrar de um livro interno do SQL Server 2008 que li (MSFT Press)):

  1. O processador de consultas obtém primeiro a tabela esquerda (tabela1)
  2. Une-se à segunda tabela (tabela2) e forma um produto cartesiano antes de filtrar as linhas necessárias (se aplicável)
  3. Em seguida, executa as cláusulas WHERE, ORDER BY, GROUP BY e HAVING com a instrução SEELCT por último.

Portanto, se na declaração nº 1 acima, a tabela for menor, o mecanismo SQL terá menos trabalho para formar os produtos cartesianos. Então, quando você alcança a instrução where, possui 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 : Apenas pensei nesta questão e ainda não tive chance de executar nenhum teste.

Nota 2 : Marcado como SQL Server, pois não sei nada sobre a implementação do MySql, etc. Por favor, sinta-se à vontade para responder / comentar de qualquer maneira

Stuart Blackler
fonte

Respostas:

15

O processamento lógico de uma consulta está no MSDN (escrito pela equipe do Microsoft SQL Server, não por terceiros)

1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

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 respeitadas ao pé da letra . O "real" é determinado pelo Query Optimizer (QO) e você evita o produto intermediário de Cartesão mencionado.

Vale ressaltar que o SQL é declarativo: você diz "o que" não "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-circuito ou ordem L-para-R WHERE)

No seu caso acima, o QO gerará o mesmo plano, independentemente de como está estruturado, porque é uma consulta simples.

No entanto, o QO é baseado em custos e, para uma consulta complexa, pode levar duas semanas para gerar o plano ideal. Por isso, faz "bom o suficiente", o que realmente 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 não pode.

Eu usei esse truque no SQL Server 2000 para obter uma melhoria de desempenho de velocidade de 60x nos relatórios de consultas. À medida que o QO melhora versão para versão, fica melhor resolvendo essas coisas.

E o livro que você mencionou: há alguma disputa sobre ele.
Consulte SO e os links subsequentes: /programming//q/3270338/27535

gbn
fonte
6

Uma consulta SQL não é de natureza processual, não há processamento de cima para baixo dos operadores de junção. A ordem das tabelas em suas consultas de exemplo não influencia o plano de execução, pois elas são logicamente equivalentes e gerarão exatamente o mesmo plano.

Você meio que avalia 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 é a estatística das tabelas envolvidas e os custos associados às opções 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, isso é errado e você pode ajudá-lo a fazer melhores escolhas através da indexação aprimorada, mantendo as estatísticas atualizadas e aplicando dicas. Em casos muito raros, convém forçar a ordem de execução usando a dica FORCE ORDER, mas isso deve ser usado com moderação. É um martelo quebrar uma noz, o otimizador geralmente pode ser provocado para gerar melhores planos, alimentando-o com mais informações.

Mark Storey-Smith
fonte