2009-06-19 10 views
131

¿Hay alguna diferencia (rendimiento, mejores prácticas, etc.) entre poner una condición en la cláusula JOIN contra la cláusula WHERE?Condición dentro de JOIN o DONDE

Por ejemplo ...

-- Condition in JOIN 
SELECT * 
FROM dbo.Customers AS CUS 
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
AND CUS.FirstName = 'John' 

-- Condition in WHERE 
SELECT * 
FROM dbo.Customers AS CUS 
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
WHERE CUS.FirstName = 'John' 

¿Qué prefieres (y tal vez por eso)?

+3

¿Has ejecutado las dos consultas? ¿Revisó los planes de ejecución generados por las dos consultas? ¿Qué observaste? –

+8

@ S.Lott, esta consulta es solo para fines ilustrativos. Me pregunto "en general", que es el método preferido, si es que hay alguno. –

+0

@Steve Dignan: Debe comparar esto con datos de muestra y observar los planes de consulta. La respuesta será muy, muy clara. Y, como beneficio adicional, tendrá una pieza de código que podrá reutilizar cuando surjan situaciones más complejas. –

Respuesta

108

El álgebra relacional permite la intercambiabilidad de los predicados en la cláusula WHERE y la INNER JOIN, por lo que incluso INNER JOIN consultas con cláusulas WHERE puede tener los predicados rearrranged por el optimizador para que ya pueden ser excluidos durante el proceso de JOIN.

Te recomiendo que escribas las consultas de la manera más leída posible.

A veces esto incluye hacer el INNER JOIN relativamente "incompleto" y poner algunos de los criterios en el WHERE simplemente para hacer que las listas de criterios de filtrado sean más fáciles de mantener.

Por ejemplo, en lugar de:

SELECT * 
FROM Customers c 
INNER JOIN CustomerAccounts ca 
    ON ca.CustomerID = c.CustomerID 
    AND c.State = 'NY' 
INNER JOIN Accounts a 
    ON ca.AccountID = a.AccountID 
    AND a.Status = 1 

Comentario:

SELECT * 
FROM Customers c 
INNER JOIN CustomerAccounts ca 
    ON ca.CustomerID = c.CustomerID 
INNER JOIN Accounts a 
    ON ca.AccountID = a.AccountID 
WHERE c.State = 'NY' 
    AND a.Status = 1 

Pero depende, por supuesto.

+13

Aumentado para agregarlo depende. Comparativa de todo. – marr75

+2

No se trata solo de consultas limpias o legibilidad, se trata de rendimiento.al poner condiciones en unirse mejora el rendimiento para una gran cantidad de datos con tablas correctamente indexadas. – Shahdat

+0

@Shahdat nunca ha visto un plan de ejecución en el que haya alguna diferencia en condiciones equivalentes en where o join –

7

WHERE se filtrará después de que se haya producido la UNIÓN.

Filtre en JOIN para evitar que se agreguen filas durante el proceso JOIN.

+8

Semánticamente, se previenen durante el proceso INNER JOIN, pero el optimizador puede reordenar INNER JOIN y DONDE predica a voluntad, por lo que el optimizador puede excluirlos más adelante si así lo desea. –

+1

Cade Roux: Derecha. A menudo, lo que escribe en SQL no es lo que el optimizador le dará cuando todo esté dicho y hecho. Supongo que esto sería lo correcto en un mundo totalmente teórico, mientras que su respuesta es, por supuesto, más correcta en el mundo de optimizadores automáticos de consultas :) – TheTXI

3

Prefiero el JOIN para unir tablas/Vistas completas y luego usar el WHERE para introducir el predicado del conjunto resultante.

Se siente sintácticamente más limpio.

0

Poner la condición en la unión me parece "semánticamente incorrecto", ya que eso no es para lo que JOINs es "para". Pero eso es muy cualitativo.

Problema adicional: si decide cambiar de una unión interna a, por ejemplo, una unión a la derecha, tener la condición dentro de la UNIÓN podría dar lugar a resultados inesperados.

+3

A veces estos resultados son un poco "esperados" y algunas veces incluso "intencionales" (para ejemplo con uniones externas, donde la condición WHERE tiene una semántica diferente que la condición JOIN). – Thetam

20

La mayoría de los productos RDBMS optimizarán ambas consultas de forma idéntica. En "SQL Performance Tuning" de Peter Gulutzan y Trudy Pelzer, probaron varias marcas de RDBMS y no encontraron diferencias en el rendimiento.

Prefiero mantener las condiciones de combinación separadas de las condiciones de restricción de consultas.

Si está usando OUTER JOIN a veces es necesario poner condiciones en la cláusula join.

+1

Estoy de acuerdo con usted en que sintácticamente es más limpio, y tengo que ceder a su conocimiento de ese libro y su gran reputación, pero puedo pensar en 4 consultas en la última semana con planes de ejecución, tiempos de CPU y lecturas lógicas muy diferentes cuando me moví donde predica a la unión. – marr75

+1

Preguntaba acerca de las mejores prácticas. Tan pronto como llegue a probar cómo funciona una implementación RDBMS específica, otras personas le han dado el consejo correcto: punto de referencia. –

2

Normalmente veo un aumento en el rendimiento al filtrar en la unión. Especialmente si puede unirse a columnas indexadas para ambas tablas. Debería poder reducir las lecturas lógicas con la mayoría de las consultas haciendo esto también, lo que es, en un entorno de alto volumen, un indicador de rendimiento mucho mejor que el tiempo de ejecución.

Siempre me divierte algo cuando alguien muestra su evaluación comparativa de SQL y han ejecutado ambas versiones de un sproc 50,000 veces a la medianoche en el servidor de desarrollo y comparan los tiempos promedio.

0

Las uniones son más rápidas en mi opinión cuando tienes una mesa más grande. Realmente no es mucha diferencia, especialmente si se trata de una mesa bastante pequeña. Cuando me enteré de las uniones, me dijeron que las condiciones en las uniones son como las condiciones de la cláusula where y que podría usarlas indistintamente si la cláusula where era específica sobre en qué tabla hacer la condición.

82

Para uniones internas Realmente no he notado la diferencia (pero como con todos los ajustes de rendimiento, debe consultar su base de datos en sus condiciones).

Sin embargo, donde pones la condición hace una gran diferencia si estás utilizando uniones hacia la izquierda o hacia la derecha. Por ejemplo considere estas dos consultas:

SELECT * 
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
WHERE ORD.OrderDate >'20090515' 

SELECT * 
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
AND ORD.OrderDate >'20090515' 

El primero le dará sólo aquellos registros que tienen una orden de fecha más tarde del 15 de mayo 2009 convirtiendo así la izquierda unirse a una combinación interna. El segundo dará esos registros más clientes sin pedidos. El conjunto de resultados es muy diferente dependiendo de dónde coloque la condición. (Seleccione * si, por ejemplo, solo, no debe usar el curso en el código de producción). La excepción a esto es cuando desea ver solo los registros en una tabla pero no en la otra. Luego usa la cláusula where para la condición, no la unión.

SELECT * 
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
WHERE ORD.OrderID is null 
+0

Gracias por explicarme con ejemplos –

+0

Gran respuesta, clara y relevante para el OP – psrpsrpsr

Cuestiones relacionadas