sql >> Base de Datos >  >> RDS >> Sqlserver

Rendimiento de INNER JOIN vs LEFT JOIN en SQL Server

A LEFT JOIN no es absolutamente más rápido que un INNER JOIN . De hecho, es más lento; por definición, una unión externa (LEFT JOIN o RIGHT JOIN ) tiene que hacer todo el trabajo de un INNER JOIN más el trabajo adicional de null-extender los resultados. También se esperaría que devuelva más filas, aumentando aún más el tiempo total de ejecución simplemente debido al mayor tamaño del conjunto de resultados.

(E incluso si un LEFT JOIN fueron más rápido en específico situaciones debido a una confluencia de factores difíciles de imaginar, no es funcionalmente equivalente a un INNER JOIN , ¡así que no puede simplemente reemplazar todas las instancias de una con la otra!)

Lo más probable es que sus problemas de rendimiento estén en otra parte, como no tener una clave candidata o una clave externa indexada correctamente. 9 mesas es bastante para unirse, por lo que la desaceleración podría estar literalmente en casi cualquier lugar. Si publica su esquema, es posible que podamos brindarle más detalles.

Editar:

Reflexionando más sobre esto, podría pensar en una circunstancia en la que LEFT JOIN podría ser más rápido que un INNER JOIN , y ahí es cuando:

  • Algunas de las mesas son muy pequeño (digamos, menos de 10 filas);
  • Las tablas no tienen índices suficientes para cubrir la consulta.

Considere este ejemplo:

CREATE TABLE #Test1
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test1 (ID, Name) VALUES (1, 'One')
INSERT #Test1 (ID, Name) VALUES (2, 'Two')
INSERT #Test1 (ID, Name) VALUES (3, 'Three')
INSERT #Test1 (ID, Name) VALUES (4, 'Four')
INSERT #Test1 (ID, Name) VALUES (5, 'Five')

CREATE TABLE #Test2
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test2 (ID, Name) VALUES (1, 'One')
INSERT #Test2 (ID, Name) VALUES (2, 'Two')
INSERT #Test2 (ID, Name) VALUES (3, 'Three')
INSERT #Test2 (ID, Name) VALUES (4, 'Four')
INSERT #Test2 (ID, Name) VALUES (5, 'Five')

SELECT *
FROM #Test1 t1
INNER JOIN #Test2 t2
ON t2.Name = t1.Name

SELECT *
FROM #Test1 t1
LEFT JOIN #Test2 t2
ON t2.Name = t1.Name

DROP TABLE #Test1
DROP TABLE #Test2

Si ejecuta esto y ve el plan de ejecución, verá que INNER JOIN de hecho, la consulta cuesta más que LEFT JOIN , porque cumple los dos criterios anteriores. Es porque SQL Server quiere hacer una coincidencia hash para INNER JOIN , pero hace bucles anidados para LEFT JOIN; el primero es normalmente mucho más rápido, pero dado que el número de filas es tan pequeño y no hay índice para usar, la operación hash resulta ser la parte más costosa de la consulta.

Puede ver el mismo efecto escribiendo un programa en su lenguaje de programación favorito para realizar una gran cantidad de búsquedas en una lista con 5 elementos, frente a una tabla hash con 5 elementos. Debido al tamaño, la versión de la tabla hash es más lenta. Pero auméntelo a 50 elementos, o 5000 elementos, y la versión de la lista se ralentiza, porque es O(N) frente a O(1) para la tabla hash.

Pero cambia esta consulta para que esté en el ID columna en lugar de Name y verás una historia muy diferente. En ese caso, realiza bucles anidados para ambas consultas, pero INNER JOIN La versión puede reemplazar uno de los escaneos de índice agrupado con una búsqueda, lo que significa que esto será literalmente un orden de magnitud más rápido con una gran cantidad de filas.

Así que la conclusión es más o menos lo que mencioné varios párrafos arriba; es casi seguro que se trata de un problema de indexación o de cobertura de índice, posiblemente combinado con una o más tablas muy pequeñas. Esas son las únicas circunstancias en las que SQL Server podría a veces elige un peor plan de ejecución para un INNER JOIN que un LEFT JOIN .