plan - optimizar sql server
Rendimiento SQL en IZQUIERDA UNIÓN EXTERNA vs NO EXISTE (6)
Answer en dba.stackexchange
Una excepción que he notado es que NOT EXISTS
es superior (aunque marginalmente) a LEFT JOIN ... WHERE IS NULL
es cuando se utilizan servidores enlazados .
Al examinar los planes de ejecución, parece que el operador NOT EXISTS
se ejecuta de forma anidada. Por lo que se ejecuta por fila (lo que supongo que tiene sentido).
Ejemplo de plan de ejecución que demuestra este comportamiento:
Si quiero encontrar un conjunto de entradas en la tabla A pero no en la tabla B, puedo usar LEFT OUTER JOIN o NOT EXISTS. Escuché que SQL Server está orientado a ANSI y, en algún caso, las UNIONES EXTERNAS IZQUIERDAS son mucho más eficientes que las que NO EXISTEN. ¿ANSI JOIN funcionará mejor en este caso? y son operadores de combinación más eficientes que NOT EXISTS en general en SQL Server?
El enlace de Joe es un buen punto de partida. Quassnoi cubre esto también.
En general, si sus campos están indexados correctamente, O si espera filtrar más registros (es decir, tiene un montón de filas EXIST
en la subconsulta) NOT EXISTS
tendrá un mejor rendimiento.
EXISTS
y NOT EXISTS
tanto cortocircuito: tan pronto como un registro coincide con los criterios, se incluye o se filtra y el optimizador pasa al siguiente registro.
LEFT JOIN
se unirá a TODOS LOS REGISTROS independientemente de si coinciden o no, luego filtrará todos los registros que no coincidan. Si sus tablas son grandes y / o tiene múltiples criterios de JOIN
, esto puede ser muy intensivo en recursos.
Normalmente trato de usar NOT EXISTS
y EXISTS
cuando sea posible. Para SQL Server, IN
y NOT IN
son semánticamente equivalentes y pueden ser más fáciles de escribir. Estos son algunos de los únicos operadores que encontrará en SQL Server que están garantizados por cortocircuito.
Esta sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join da ejemplos de varias maneras ( NO EN , SOLICITUD EXTERNA , UNIÓN EXTERIOR EXTERIOR , EXCEPTO y NO EXISTE ) para lograr los mismos resultados y demuestra que no existe (combinación Anti Izquierda Semi) es la mejor opción tanto en memoria caché fría como en memoria caché escenarios.
La mejor discusión que he leído sobre este tema para SQL Server está here .
Me he estado preguntando cómo podemos usar el índice en la tabla de la que estamos eliminando en estos casos que describe el OP.
Digamos que tenemos:
table EMPLOYEE (emp_id int, name varchar)
and
table EMPLOYEE_LOCATION (emp_id int, loc_id int)
En mi ejemplo del mundo real, mis tablas son mucho más amplias y contienen 1 millón de filas +, he simplificado el esquema por ejemplo.
Si quiero eliminar las filas de EMPLOYEE_LOCATION que no tienen emp_id''s correspondientes en EMPLOYEE, obviamente puedo usar la técnica externa Left o NOT IN pero me preguntaba ...
Si ambas tablas tienen índices con la columna principal de emp_id, ¿valdría la pena intentar usarlas?
Quizás podría extraer el emp_id de EMPLOYEE, el emp_id de EMPLOYEE_LOCATION en una tabla temporal y obtener el emp_id de las tablas temporales que quiero eliminar.
Podría pasar por estos emp_id y utilizar el índice de la siguiente manera:
loop for each emp_id X to delete -- (this would be a cursor)
DELETE EMPLOYEE_LOCATION WHERE emp_id = X
Sé que hay una sobrecarga con el cursor, pero en mi ejemplo real, estoy tratando con tablas enormes, así que creo que el uso explícito del índice es deseable.
Personalmente, creo que este se pone viejo, "Depende". He visto instancias donde cada método ha superado al otro.
Su mejor apuesta es probar ambos y ver cuál rinde mejor. Si se trata de una situación en la que las tablas siempre serán pequeñas y el rendimiento no es tan importante, entonces elegiré el que sea más claro para ti (normalmente NOT EXISTS
para la mayoría de las personas) y seguiré adelante.