Tengo dos mesas
@T1 TABLE
(
Id INT,
Date DATETIME
)
@T2 TABLE
(
Id INT,
Date DATETIME
)
Estas tablas tienen un índice no agrupado en (Id, Fecha)
Y me uno a estas mesas
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
WHERE
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Esto también se puede escribir como
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
AND
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Mi pregunta es, ¿cuál de estas dos consultas ofrece el mejor rendimiento y por qué? ¿O son iguales?
Respuestas:
El rendimiento será el mismo. El optimizador lo reconocerá y creará el mismo plan.
Por otro lado, no diría que son iguales. La primera forma en la pregunta es mucho más legible y generalmente esperada.
Para un ejemplo usando algunas tablas que tengo a mano, puede ver que el plan de ejecución es exactamente el mismo sin importar cómo escriba la consulta.
Sin embargo, debe poder determinar los planes de consulta para sus propias tablas y conjunto de datos para poder ver qué sucede en su situación.
Da estos planes de ejecución
fuente
INNER JOIN
. Si lanzas un lanzamiento,OUTER JOIN
entonces definitivamente no son lo mismo.Son semánticamente idénticos y el optimizador no debería tener problemas para reconocer este hecho y generar planes idénticos.
Tiendo a poner condiciones que hacen referencia a ambas tablas en
ON
y condiciones que hacen referencia a una sola tabla enWHERE
.OUTER JOINS
Sin embargo, para moverse, las condiciones pueden afectar la semántica.fuente
En casos simples, será lo mismo. Sin embargo, he visto consultas muy complejas con varias combinaciones que tienen planes significativamente diferentes. Una reciente en la que estaba trabajando comenzó con una tabla que tiene cerca de 6 millones de filas unidas a unas 20 tablas diferentes. Solo la primera unión a esta tabla fue una unión interna , todas las demás quedaron juntas externas. El filtro en la cláusula where se parametrizó de la siguiente manera:
Este filtro se usó más tarde en el plan en lugar de antes. Cuando moví estas condiciones a la primera unión interna, el plan cambió drásticamente a medida que el filtro se aplicó al principio del plan para limitar el conjunto de resultados y mi CPU y el tiempo transcurrido disminuyeron aproximadamente un 310%. Entonces, como con muchas preguntas de SQL Server, depende.
fuente
En general, donde pones los filtros hace la diferencia.
Si bien Tom V dice que el Optimizador reconocerá que las consultas son las mismas y propondrá el mismo plan, eso no siempre es cierto. Depende de la versión de SQL en la que se encuentre, la complejidad de su consulta y la importancia del lote general que el Optimizer determina que es la consulta.
El Optimizador puede decidir que esta parte del lote no vale la pena dedicar el tiempo suficiente para permitirle encontrar el mejor plan. En general, obtendrá un mejor rendimiento si coloca condiciones que reducen la cantidad de datos en los que la consulta necesitará trabajar en la cláusula ON en lugar de la cláusula WHERE (si es posible, ya que hacer esto con una combinación externa dará como resultado un producto cartesiano .)
Es un poco más fácil para el desarrollador SQL ocasional detectar filtros en la cláusula WHERE, pero he trabajado en algunas tablas grandes donde tener los filtros en la cláusula ON recorta horas del tiempo de ejecución.
Entonces, si la cláusula tiene el potencial de reducir drásticamente el número de filas que leerá la consulta, siempre la pondré en la cláusula ON para ayudar al Optimizador a elegir el mejor plan.
fuente
En circunstancias normales, las condiciones de filtro se pueden especificar en las cláusulas WHERE o JOIN. Tiendo a colocar filtros debajo de DONDE, a menos que la prioridad de OUTER JOIN pueda verse afectada (ver más abajo) o si el filtro es muy específico para esa tabla (por ejemplo, TYPE = 12 para especificar un subconjunto específico de filas en la tabla).
Por otro lado, las cláusulas ON y WHERE pueden usarse para especificar condiciones de unión (en oposición a las condiciones de filtro). Mientras use solo combinaciones INNER, no importará cuál use en circunstancias normales.
Sin embargo, si está utilizando combinaciones OUTER, puede hacer una gran diferencia. Si, por ejemplo, especifica una UNIÓN EXTERNA entre dos tablas (t1 y t2) pero luego, en la cláusula WHERE, especifica una relación eqijoin entre las tablas (por ejemplo, t1.col = t2.col), simplemente tiene ¡Convirtió la unión EXTERIOR en una unión INTERNA! Esto se debe a que WHERE se puede usar para especificar un equijoin (o tal vez incluso una unión OUTER, dependiendo de la versión, usando la sintaxis obsoleta * =) sin usar una cláusula ON, y cuando WHERE indica un equijoin interno entre las tablas, anula un OUTER ÚNETE (si está presente).
La pregunta original era acerca de los filtros, donde el tipo de unión a menudo no debería ser un problema, pero una unión también puede actuar como un filtro y en esas situaciones la ubicación de la condición de unión ciertamente puede importar.
fuente
Con INNER JOINs, es un problema de estilo.
Sin embargo, se vuelve mucho más interesante con OUTER JOINs. Debe explorar las diferencias entre las consultas con OUTER JOIN y las condiciones tanto en la cláusula ON como en la cláusula WHERE. El conjunto de resultados no siempre es el mismo. Es, por ejemplo,
lo mismo que
fuente