2009-04-30 11 views
7

Dadas estas dos consultas:¿es mejor poner más lógica en su cláusula ON o solo debe tener el mínimo necesario?

Select t1.id, t2.companyName 
from table1 t1 
    INNER JOIN table2 t2 on t2.id = t1.fkId 
WHERE t2.aField <> 'C' 

O:

Select t1.id, t2.companyName 
from table1 t1 
    INNER JOIN table2 t2 on t2.id = t1.fkId and t2.aField <> 'C' 

¿Hay una diferencia demostrable entre los dos? Me parece que la cláusula "t2.aField <> 'C'" se ejecutará en cada fila en t2 que cumpla con los criterios de unión independientemente. ¿Soy incorrecto?

Actualización: Realicé un "Incluir plan de ejecución real" en SQL Server. Las dos consultas fueron idénticas.

Respuesta

4

Prefiero utilizar los criterios de combinación para explicar cómo se unen las tablas. Así que colocaría la cláusula adicional en la sección donde.

Espero (aunque no tengo estadísticas) que SQL Server sea lo suficientemente astuto como para encontrar el plan de consulta óptimo independientemente de la sintaxis que utilice.

SIN EMBARGO, si tiene índices que también tienen identificación y un campo en ellos, le sugiero que los coloque juntos en los criterios de unión interna.

Sería interesante ver el plan de consulta en estos 2 (o 3) escenarios, y ver qué pasa. Buena pregunta.

+0

Acepto, si es parte de un índice, debe estar en la cláusula ON y si se trata de criterios de filtrado debe ir en la cláusula WHERE. Esto tiene suficientes votos ascendentes para llamarlo la respuesta. – jcollum

3

Hay una diferencia. Debe hacer un PLAN DE EXPLICACIÓN para los dos seleccionados y verlo en detalle.

En cuanto a una explicación simplista: La cláusula WHERE se ejecuta solo después de la unión de las dos tablas, por lo que se ejecuta para cada fila devuelta desde la unión y no necesariamente cada una de la tabla2.

Rendimiento sabio es el mejor para eliminar los resultados no deseados desde el principio por lo que debe haber menos filas para las uniones, donde las cláusulas u otras operaciones para hacer frente más adelante.

En el segundo ejemplo, hay 2 columnas que tienen que ser iguales para las filas que se unirán, por lo que generalmente dará resultados diferentes a la primera.

+0

Un producto de base de datos tan estúpido como eso sería un braindead. Por supuesto, cualquier implementación de base de datos que valga su nombre no incluye uniones innecesarias –

+0

Sí, lo he intentado antes en MySQL. Al menos en mi caso, no hubo diferencia en la velocidad –

+0

Para una simple combinación natural de dos tablas, no habrá ninguna diferencia. Pero, se nota cuando tienes que unirte a 5-6 tablas y luego incluso la implementación "inteligente" de la base de datos tendrá que ser ayudada. – Azder

0

Prefiero la primera consulta. El servidor SQL usará el mejor tipo de combinación para su consulta en función de los índices que tenga, después de eso aplicará la cláusula WHERE. Pero puede ejecutar ambas consultas al mismo tiempo, ver los planes de ejecución, comparar y elegir el más rápido (optimizar también agregar índices).

+0

controle el rendimiento de sus escrituras cada vez que agregue índices. Existen métodos disponibles para sus índices que los hacen "fáciles de escribir". – yetanotherdave

2

Depende.

SELECT 
    t1.foo, 
    t2.bar 
FROM 
    table1 t1 
    LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId 
WHERE 
    t2.SomeValue IS NULL 

es diferente de

SELECT 
    t1.foo, 
    t2.bar 
FROM 
    table1 t1 
    LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId AND t2.SomeValue IS NULL 

Es diferente porque los primeros cruces con todos los registros de t2 que tienen NULL en t2.SomeValue y los de T1 que no se hace referencia en t2. Este último tacha solo los registros t2 que tienen NULL en t2.SomeValue.

Simplemente use la cláusula ON para la condición de unión y la cláusula WHERE para el filtro.

+0

Aunque utilicé una unión interna en mi muestra. – jcollum

+0

su muestra es diferente porque t2.SomeValue podría ser nulo porque no se unió o se unió y el campo es nulo – jcollum

+0

La diferencia está en NULL. En la combinación de la izquierda, t2.SomeValue será NULL cuando * en realidad sea * NULL, * y * será NULL cuando no se haga referencia a un registro de t1. Los conjuntos de resultados no son iguales. La única forma de diferenciarlos es usar la cláusula ON. – Tomalak

0

a menos que esté trabajando en una aplicación para un solo usuario o algo similar que crea una carga trivial, las únicas consideraciones que tienen sentido es cómo el servidor procesará su consulta.

Las respuestas que mencionan planes de consulta dan buenos consejos.

Además, establezca las estadísticas io para tener una idea de cuántas lecturas generará su consulta (me gusta especialmente la publicación de Azder).

Piense en cada servidor de base de datos como una bomba de datos desde el disco al cliente. Esa bomba funciona más rápido si solo realiza el IO necesario para realizar el trabajo. Si los datos están en caché, serán aún más rápidos. Pero no querrá leer más de lo que necesita del disco, lo que provocará que se eliminen los datos útiles de su caché sin una buena razón.

1

A menos que mover la condición de unión a la cláusula where cambie el significado de la consulta (como en el ejemplo de la combinación de la izquierda anterior), entonces no importa dónde los coloque. SQL los reorganizará y, siempre que sean equivalentes, obtendrá la misma consulta.

Habiendo dicho eso, creo que es más una cosa lógica/de legibilidad. Normalmente pongo todo lo que relaciona dos tablas en la combinación, y cualquier cosa que se filtre en el lugar.

+0

Hay una advertencia menor a esta respuesta. Teóricamente, no hace ninguna diferencia dónde colocas tus condiciones. Sin embargo, en la práctica, el optimizador tiene un tiempo limitado para reorganizar la consulta, por lo que es posible que no haya tenido tiempo de volver a solicitar sus condiciones de suscripción. Por lo tanto, en algunos casos con consultas muy complicadas, podría ser importante. –

Cuestiones relacionadas