¿Existe alguna práctica recomendada entre el uso de un formato LEFT JOIN o NOT EXISTS?
¿Cuál es el beneficio de usar uno sobre el otro?
Si no hay ninguno, ¿cuál debería preferirse?
SELECT *
FROM tableA A
LEFT JOIN tableB B
ON A.idx = B.idx
WHERE B.idx IS NULL
SELECT *
FROM tableA A
WHERE NOT EXISTS
(SELECT idx FROM tableB B WHERE B.idx = A.idx)
Estoy usando consultas dentro de Access contra una base de datos de SQL Server.
sql-server
join
exists
Michael Richardson
fuente
fuente

WHERE A.idx NOT IN (...)es no idéntica , debido al comportamiento de trivalenteNULL(es decir,NULLno es igual aNULL(ni desigual), por lo tanto, si usted tiene cualquieraNULLdetableBobtendrá resultados inesperados!)Respuestas:
La mayor diferencia no está en la combinación vs no existe, es (como está escrito), el
SELECT *.En el primer ejemplo, obtienes todas las columnas de ambos
AyB, mientras que en el segundo ejemplo, obtienes solo columnas deA.En SQL Server, la segunda variante es ligeramente más rápida en un ejemplo artificial muy simple:
Crea dos tablas de muestra:
Inserte 10,000 filas en cada tabla:
Eliminar cada quinta fila de la segunda tabla:
Realice las dos
SELECTvariantes de declaración de prueba :Planes de ejecución:
La segunda variante no necesita realizar la operación de filtro ya que puede usar el operador izquierdo anti-semi-unión.
fuente
Lógicamente son idénticos, pero
NOT EXISTSestá más cerca del AntiSemiJoin que está solicitando, y generalmente se prefiere. También resalta mejor que no puede acceder a las columnas en B, porque solo se usa como un filtro (en lugar de tenerlas disponibles con valores NULL).Hace muchos años (SQL Server 6.0 ish),
LEFT JOINfue más rápido, pero ese no ha sido el caso durante mucho tiempo. En estos días,NOT EXISTSes marginalmente más rápido.El mayor impacto en Access es que el
JOINmétodo tiene que completar la unión antes de filtrarla, construyendo el conjunto unido en la memoria. UsarloNOT EXISTSverifica la fila pero no asigna espacio para las columnas. Además, deja de buscar una vez que encuentra una fila. El rendimiento varía un poco más en Access, pero una regla general es queNOT EXISTStiende a ser un poco más rápido. Me inclinaría menos a decir que es "la mejor práctica", ya que hay más factores involucrados.fuente
Una excepción que he notado por
NOT EXISTSser superior (aunque marginalmente)LEFT JOIN ... WHERE IS NULLes cuando utilizo servidores vinculados .Al examinar los planes de ejecución, parece que el
NOT EXISTSoperador se ejecuta en forma de bucle anidado. Por el cual se ejecuta por fila (lo que supongo que tiene sentido).Ejemplo de plan de ejecución que demuestra este comportamiento:
fuente
INSERT INTO #t (a,b,c) SELECT a,b,c FROM LinkedServer.database.dbo.table WHERE x=yluego ejecutandoNOT EXISTS (...)esa copia temporal de la base de datos.En general, el motor creará un plan de ejecución basado esencialmente en:
Para 4):
El plan "no existe" alienta un plan basado en la búsqueda en la tabla B. Esta es una buena opción cuando la tabla A es pequeña y la tabla B es grande (y existe un índice en B).
El plan "anti-unión" es una buena opción cuando la tabla A es muy grande o la tabla B es muy pequeña o no hay índice en B y devuelve un gran conjunto de resultados.
Sin embargo, es solo un "estímulo", como una entrada ponderada. Un fuerte (1), (2), (3) a menudo hace la elección de (4) discutible.
(Ignorando el efecto de su ejemplo que devuelve diferentes columnas debido al *, abordado por la respuesta @MaxVernon).
fuente