Como todos los temas de optimización las soluciones presentadas en éste artículo deben probarse,
intentar varias alternativas y luego decidir dependiendo de los
resultados y especialmente de la evolución de los datos, es decir, dependiendo del
momento del ciclo de vida de la base de datos tendremos cierto uso de
la información (por ejemplo durante procesos de migración) y luego
tendremos otro tipo (en Producción, cuando cierto tipo de producto salga
de circulación, etc.)
El proceso de optimización y mantenimiento es algo continuo y
debe estar acorde a las necesidades y cambios del negocio
Pimero, qué es un SEMI JOIN
SELECT HumanResources.Employee.BusinessEntityID, MyEmployees.EmployeeID
FROM HumanResources.Employee LEFT OUTER JOIN
MyEmployees ON HumanResources.Employee.BusinessEntityID = MyEmployees.EmployeeID
Es cuando queremos hacer un left (o Right join) con otra(s) tabla(s) y queremos ver qué registros figuran en la primera tabla (HumanResources.Employee) y cuales en la segunda(MyEmployees)
Si en la segunda tabla no existe dicho registro se presentará NULL como se vé en la gráfica
Ahora, Definamos un ANTI SEMI JOIN
SELECT HumanResources.Employee.BusinessEntityID, MyEmployees.EmployeeID
FROM HumanResources.Employee LEFT OUTER JOIN
MyEmployees ON HumanResources.Employee.BusinessEntityID = MyEmployees.EmployeeID
WHERE (MyEmployees.EmployeeID IS NULL)
Queremos encontrar los registros que estén en la primera tabla (HumanResources.Employee) que NO estén en la segunda tabla (MyEmployee)
Ésta consulta cumple su cometido pero analicemos a fondo su funcionamiento, realiza el Left Join que mas pesado que realizar un inner join normal y filtra los resultados para la columna null
Ahora, qué ALTERNATIVA tenemos para éste caso:
Usaremos la función Exists
SELECT a.BusinessEntityID
FROM HumanResources.Employee a
where not exists(select EmployeeID from MyEmployees b where a.BusinessEntityID = b.EmployeeID)
Observemos la comparación entre el primer método y la alternativa:
El costo relativo para el batch es el mismo, y aparentemente tienen el mismo costo, pero observemos 2 cosas interesantes sobre éste plan de ejecución, primero es que de la primera manera tenemos un filtro, es de recordar que los ordenamientos, las agrupaciones y los filtros son las operaciones más costosas dentro de una consulta; en la segunda parte ejecutando con Not Exists, vemos que el analizador identifica que es un Left Anti Semi Join, por lo cual automáticamente aplica las optimizaciones para este caso y luego realiza las operaciones adicionales de la consulta
Usando repetidamente ésta técnica, especialmente para consultas que impliquen muchos registros puede aumentar el rendimiento de la misma a la vez que permite una facil escritura y mantenimiento e incluso control sobre la consulta a realizar
FREDDY LEANDRO ANGARITA CASTELLANOS
Sql Server MVP