¿Alguna idea de por qué la IF EXISTS
haría funcionar mucho más tiempo y hacer tantas lecturas más? También cambié la declaración select para hacer SELECT TOP 1 [dlc].[id]
y la maté después de 2 minutos.
Como expliqué en mi respuesta a esta pregunta relacionada:
¿Cómo (y por qué) TOP impacta un plan de ejecución?
El uso EXISTS
introduce un objetivo de fila, donde el optimizador produce un plan de ejecución destinado a ubicar la primera fila rápidamente. Al hacer esto, se supone que los datos se distribuyen uniformemente. Por ejemplo, si las estadísticas muestran que hay 100 coincidencias esperadas en 100,000 filas, se supondrá que tendrá que leer solo 1,000 filas para encontrar la primera coincidencia.
Esto dará como resultado tiempos de ejecución más largos de lo esperado si esta suposición resulta ser defectuosa. Por ejemplo, si SQL Server elige un método de acceso (por ejemplo, exploración no ordenada) que localiza el primer valor coincidente muy tarde en la búsqueda, podría resultar en una exploración casi completa. Por otro lado, si se encuentra una fila coincidente entre las primeras filas, el rendimiento será muy bueno. Este es el riesgo fundamental con los objetivos de la fila: rendimiento inconsistente.
Como arreglo temporal, lo he cambiado para que cuente (*) y asigne ese valor a una variable
Por lo general, es posible reformular la consulta de modo que no se asigne un objetivo de fila. Sin el objetivo de la fila, la consulta aún puede finalizar cuando se encuentra la primera fila coincidente (si se escribe correctamente), pero es probable que la estrategia del plan de ejecución sea diferente (y con suerte, más efectiva). Obviamente, count (*) requerirá leer todas las filas, por lo que no es una alternativa perfecta.
Si está ejecutando SQL Server 2008 R2 o posterior, generalmente también puede usar el indicador de seguimiento 4138 documentado y compatible para obtener un plan de ejecución sin un objetivo de fila. Este indicador también se puede especificar utilizando la sugerencia compatible OPTION (QUERYTRACEON 4138)
, aunque tenga en cuenta que requiere permiso de administrador del sistema en tiempo de ejecución , a menos que se use con una guía de plan.
Desafortunadamente
Ninguno de los anteriores es funcional con una IF EXISTS
declaración condicional. Solo se aplica a DML normal. Se va a trabajar con el suplente SELECT TOP (1)
formulación que ha intentado. Eso puede ser mejor que usar COUNT(*)
, que tiene que contar todas las filas calificadas, como se mencionó anteriormente.
Dicho esto, hay varias formas de expresar este requisito que le permitirán evitar o controlar el objetivo de la fila, mientras finaliza la búsqueda antes de tiempo. Un último ejemplo:
DECLARE @Exists bit;
SELECT @Exists =
CASE
WHEN EXISTS
(
SELECT [dlc].[ID]
FROM TableDLC [dlc]
JOIN TableD [d]
ON [d].[ID] = [dlc].[ID]
JOIN TableC [c]
ON [c].[ID] = [d].[ID2]
WHERE [c].[Name] <> [dlc].[Name]
)
THEN CONVERT(bit, 1)
ELSE CONVERT(bit, 0)
END
OPTION (QUERYTRACEON 4138);
IF @Exists = 1
BEGIN
...
END;
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
.