¿Qué es mejor: muchas condiciones de unión o muchas condiciones donde?

13

Estoy tratando de comparar dos 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 

¿Tengo razón al decir que estas dos consultas dan los mismos resultados?

Además, ¿es correcto decir que la primera consulta crea una tabla más grande para la cual hacer una WHEREcondición más grande ? mientras que en el segundo caso tenemos una tabla construida más pequeña a la que WHEREluego se aplica lo simple .

Suponiendo que los resultados son los mismos, ¿qué consulta debería preferirse? ¿Hay un problema de rendimiento obvio?

Geoff
fuente
3
No, no tienes razón al decir eso. Sería si eso fuera un INNER JOIN, pero con un LEFT JOINesto devolverá resultados diferentes. Básicamente, las condiciones que agregó en WHEREsu segunda consulta están convirtiendo su JOINen unINNER JOIN
Lamak
Ah ok Sigo lo que dices. Si edito para INNER JOINque mis preguntas sobre el rendimiento sigan siendo válidas?
Geoff
44
Para INNER JOINs no debería haber diferencia en el rendimiento. Dicho esto, para facilitar la lectura y la expresión adecuada de la intención, debe utilizar los criterios de combinación en los ONcriterios de filtro y en WHERE.
Aaron Bertrand
@ypercube bien, perdí esa condición.
Lamak 01 de

Respuestas:

10

Si consideramos que usa en INNER JOINlugar de LEFT JOIN(lo cual parece ser su intención), estas dos consultas son funcionalmente equivalentes. Los optimizadores de consultas revisarán y evaluarán los criterios en su WHEREcláusula y su FROMcláusula y considerarán todos estos factores al crear planes de consulta para alcanzar el plan de ejecución más eficiente. Si hacemos un EXPLAINen ambas declaraciones, obtenemos el mismo 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 |

Puede revisar los detalles completos con los siguientes enlaces. También creé un ejemplo de SQL 2008 para que pueda comparar cómo funcionan los dos motores (que es lo mismo):

Ejemplo de consulta MySQL

Ejemplo de consulta SQL 2008 (asegúrese de 'Ver plan de ejecución' para ambos resultados)

Mike Fal
fuente
Gracias por tu solución detallada. Lo intenté en INNER JOINlugar de LEFT JOINy obtuve el mismo resultado en una décima parte del tiempo. Creo que sé por qué obtengo el mismo resultado, pero ¿por qué tendría un INNER JOINmejor rendimiento?
Geoff
44
Como LEFT JOINes una unión externa, no puede restringir el conjunto de datos en el lado de retorno completo del conjunto e intentará recuperar todas las filas de esa tabla (en este caso, Tabla A). Si lo usa INNER JOIN, puede aprovechar ese criterio en ambas tablas y restringir el conjunto de datos, proporcionando así un retorno más rápido.
Mike Fal