Cuando ejecuto el siguiente código, toma 22.5 minutos y hace 106 millones de lecturas. Sin embargo, si ejecuto solo la instrucción de selección interna por sí sola, solo toma 15 segundos y hace 264k lecturas. Como nota al margen, la consulta de selección no devuelve ningún registro.
¿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 arreglo temporal, lo he cambiado para hacer un recuento (*) y asignar ese valor a una variable @cnt
. Entonces hace una IF 0 <> @cnt
declaración. Pero pensé EXISTS
que sería mejor, porque si había registros devueltos en la instrucción select, dejaría de realizar la exploración / búsqueda una vez que encontrara al menos un registro, mientras count(*)
que completará la consulta completa. ¿Qué me estoy perdiendo?
IF 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])
BEGIN
<do something>
END
fuente
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
.Respuestas:
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.
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 suplenteSELECT TOP (1)
formulación que ha intentado. Eso puede ser mejor que usarCOUNT(*)
, 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:
fuente
Debido a que EXISTS solo necesita encontrar una sola fila, utilizará un objetivo de fila de una. Esto puede producir un plan menos que ideal a veces. Si espera que sea así para usted, complete una variable con el resultado de a
COUNT(*)
y luego pruebe esa variable para ver si es más de 0.Entonces ... Con un objetivo de fila pequeño, evitará operaciones de bloqueo, como construir tablas hash u ordenar flujos que podrían ser útiles para unir combinaciones, porque se dará cuenta de que seguramente encontrará algo bastante rápido y, por lo tanto, los bucles anidados lo harían. Sería mejor si encontrara algo. Excepto que esto puede hacer un plan que es mucho peor en todo el conjunto. Si encontrar una sola fila fuera rápido, le gustaría este método para evitar bloques ...
fuente