¿Una unión está optimizada para una cláusula where en tiempo de ejecución?

14

Cuando escribo una consulta como esta ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

¿El optimizador de SQL, no estoy seguro si ese es el término correcto, lo traduce a ...

select *
from table1 t1, table2 t2
where t1.id = t2.id

Básicamente, ¿la declaración Join en SQL Server es solo una forma más fácil de escribir sql? ¿O se usa realmente en tiempo de ejecución?

Editar: casi siempre, y casi siempre, uso la sintaxis Join. Tengo curiosidad por saber qué sucede.

Señor hormiga
fuente
1
¿Podrías dar más detalles sobre el "casi"? ¿Cuándo usarías la sintaxis antigua y por qué?
Aaron Bertrand
2
Un caso extremo en el que sí hace la diferencia es si agrega un (en desuso) GROUP BY ALLen
Martin Smith
@MartinSmith, ¿alguien lo usa GROUP BY ALLa propósito? :-)
Aaron Bertrand
@AaronBertrand - ¡Lo dudo! No creo que haya visto a nadie usarlo.
Martin Smith

Respuestas:

20

Esos colapsan a lo mismo internamente. El primero es el que siempre debes escribir . Más importante aún, ¿por qué importa? Son idénticos en términos de plan de ejecución y rendimiento (suponiendo que no lo estropees, lo cual es más fácil de hacer con la sintaxis perezosa y antigua).

Aquí hay una prueba usando AdventureWorks de que no existe CROSS JOINy filtercontinúa.


La unión explícita:

ingrese la descripción de la imagen aquí


La unión implícita:

ingrese la descripción de la imagen aquí


Mira ma! Planes idénticos, resultados idénticos, sin cruces ni filtros vistos en ningún lado.

(Para mayor claridad, la advertencia sobre el SELECToperador en ambos casos es una conversión implícita que afecta la cardinalidad, nada que ver con la unión en ninguno de los casos).

Aaron Bertrand
fuente
20

Estrictamente hablando, hay una diferencia en la entrada al optimizador de consultas entre las dos formas:

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Árbol de entrada ISO-89

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Árbol de entrada ISO-92

Como puede ver, el ONpredicado de la cláusula está estrechamente vinculado a la unión mediante la sintaxis moderna. Con la sintaxis anterior, hay una unión cruzada lógica seguida de una selección relacional (un filtro de fila).

El optimizador de consultas casi siempre colapsa la selección relacional en la unión durante la optimización, lo que significa que es muy probable que los dos formularios produzcan planes de consulta equivalentes, pero no hay garantía real.

Paul White 9
fuente
4

Para la unión interna son intercambiables, pero para las uniones externas tienen diferentes significados: el ON coincide y el WHERE es un filtrado simple. Por lo tanto, es mejor atenerse a la sintaxis correcta de JOIN en ON.

DaniSQL
fuente
4

OK, tenía curiosidad, así que hice una prueba. Tengo planes de ejecución reales para lo siguiente.

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

y

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

Los comparé objeto por objeto y eran idénticos. Entonces, al menos para un ejemplo muy simple, salieron a la misma cosa. También verifiqué las estadísticas IO y el tiempo y estaban lo suficientemente cerca como para ser lo mismo.

Dicho esto, debe usar la JOINsintaxis porque es más fácil de leer y es menos probable que cometa errores, especialmente en consultas complicadas. Y el *=/ =*la sintaxis de OUTERlas combinaciones ya se ha eliminado como de SQL Server 2005.

Kenneth Fisher
fuente