O que é melhor: muitas condições de junção ou muitas condições de onde?

13

Estou tentando comparar duas consultas:

Consulta 1:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a
WHERE tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  AND tableA.e=tableB.e 

Consulta 2:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a AND tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  
WHERE tableA.e=tableB.e 

Estou certo em dizer que essas duas consultas fornecem os mesmos resultados?

Além disso, é correto dizer que a primeira consulta cria uma tabela maior para a qual fazer uma WHEREcondição maior ; enquanto que no segundo caso, temos uma tabela construída menor à qual o simples WHEREé então aplicado.

Supondo que os resultados sejam os mesmos, qual consulta deve ser preferida? Existe um problema de desempenho óbvio?

Geoff
fonte
3
Não, você não está certo ao dizer isso. Seria se fosse um INNER JOIN, mas com um LEFT JOINisso retornará resultados diferentes. Basicamente, as condições que você adicionou na WHEREem sua segunda consulta estão convertendo o seu JOINem umINNER JOIN
Lamak
Ah ok. Eu sigo o que você diz. Se eu editar para INNER JOINfazer minhas perguntas sobre desempenho permanecerem válidas?
Geoff
4
Para INNER JOINs, não deve haver diferença no desempenho. Dito isto, para legibilidade e expressão adequada da intenção, você deve usar os critérios de junção nos ONcritérios de filtro e WHERE.
Aaron Bertrand
@ypercube certo, eu perdi essa condição.
Lamak

Respostas:

10

Se considerarmos que você usa em INNER JOINvez de LEFT JOIN(que parece ser sua intenção), essas duas consultas são funcionalmente equivalentes. Os otimizadores de consulta revisarão e avaliarão os critérios em sua WHEREcláusula e sua FROMcláusula e considerarão todos esses fatores ao criar planos de consulta para alcançar o plano de execução mais eficiente. Se fizermos um EXPLAINem ambas as instruções, obteremos o mesmo resultado:

Consulta 1 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
WHERE 
  tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
  AND tableA.ColE=tableB.ColE

[Resultados] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

Consulta 2 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
  AND tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
WHERE
  tableA.ColE=tableB.ColE

[Resultados] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

Você pode revisar os detalhes completos com os seguintes links. Também criei um exemplo do SQL 2008 para que você possa comparar como os dois mecanismos funcionam (que é o mesmo):

Exemplo de consulta MySQL

Exemplo de consulta do SQL 2008 (verifique 'Exibir plano de execução' para os dois resultados)

Mike Fal
fonte
Obrigado pela sua solução detalhada. Tentei em INNER JOINvez de LEFT JOINe recebo a mesma saída em um décimo do tempo. Acho que sei por que obtenho a mesma saída, mas por que um INNER JOINdesempenho melhor?
Geoff
4
Como LEFT JOINé uma junção externa, ele não pode restringir o conjunto de dados no lado de retorno completo do conjunto e tentará recuperar todas as linhas dessa tabela (nesse caso, TabelaA). Se você usar INNER JOIN, ele poderá aproveitar esse critério nas duas tabelas e restringir o conjunto de dados, proporcionando um retorno mais rápido.
Mike Fal