Cuando una consulta SQL previamente rápida comienza a ejecutarse lentamente, ¿dónde busco para encontrar el origen del problema?


37

Fondo

Tengo una consulta en ejecución contra SQL Server 2008 R2 que une y / o une a la izquierda unas 12 "tablas" diferentes. La base de datos es bastante grande con muchas tablas de más de 50 millones de filas y unas 300 tablas diferentes. Es para una compañía grande que tiene 10 almacenes en todo el país. Todos los almacenes leen y escriben en la base de datos. Entonces es bastante grande y bastante ocupado.

La consulta con la que tengo problemas se parece a esto:

select t1.something, t2.something, etc.
from Table1 t1
    inner join Table2 t2 on t1.id = t2.t1id
    left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
    [etc]...
where t1.something = 123

Observe que una de las combinaciones está en una subconsulta no correlacionada.

El problema es que a partir de esta mañana, sin ningún cambio (que yo o cualquiera de mi equipo sepa) del sistema, la consulta, que generalmente demora aproximadamente 2 minutos en ejecutarse, comenzó a tardar una hora y media en ejecutarse, cuando corrió en absoluto. El resto de la base de datos está funcionando bien. Tomé esta consulta del sproc en el que generalmente se ejecuta y la ejecuté en SSMS con variables de parámetros codificadas con la misma lentitud.

Lo extraño es que cuando tomo la subconsulta no correlacionada y la tiro a una tabla temporal, y luego la uso en lugar de la subconsulta, la consulta funciona bien. Además (y esto es lo más extraño para mí) si agrego este código al final de la consulta, la consulta se ejecuta muy bien:

and t.name like '%'

Llegué a la conclusión (tal vez incorrectamente) de estos pequeños experimentos que la razón de la desaceleración se debe a cómo se configura el plan de ejecución en caché de SQL: cuando la consulta es un poco diferente, tiene que crear un nuevo plan de ejecución.

Mi pregunta es la siguiente: cuando una consulta que solía ejecutarse rápidamente, de repente comienza a ejecutarse lentamente en medio de la noche y nada más se ve afectado, excepto esta consulta, ¿cómo lo soluciono y cómo evito que suceda en el futuro? ? ¿Cómo sé qué está haciendo SQL internamente para hacerlo tan lento (si se ejecuta la consulta incorrecta, podría obtener su plan de ejecución pero no se ejecutará, ¿tal vez el plan de ejecución esperado me daría algo?)? Si este problema es con el plan de ejecución, ¿cómo evito que SQL piense que los planes de ejecución realmente malos son una buena idea?

Además, esto no es un problema con la detección de parámetros. Lo he visto antes, y esto no es así, ya que incluso cuando codifico los valores en SSMS, sigo obteniendo un rendimiento lento.


¿Podría compartir el plan de consulta (el lento) aquí: brentozar.com/pastetheplan
MJH

Respuestas:


32

Cuando una consulta que solía ejecutarse rápidamente, de repente comienza a ejecutarse lentamente en medio de la noche y nada más se ve afectado, excepto esta consulta, ¿cómo puedo solucionarlo ...?

Puede comenzar comprobando si el plan de ejecución todavía está en la memoria caché. Comprobar sys.dm_exec_query_stats, sys.dm_exec_procedure_statsy sys.dm_exec_cached_plans. Si el plan de ejecución incorrecto todavía se almacena en caché, puede analizarlo y también puede verificar las estadísticas de ejecución. Las estadísticas de ejecución contendrán información como lecturas lógicas, tiempo de CPU y tiempo de ejecución. Estos pueden dar fuertes indicaciones de cuál es el problema (p. Ej., Exploración grande versus bloqueo). Consulte Identificación de consultas problemáticas para obtener una explicación sobre cómo interpretar los datos.

Además, esto no es un problema con la detección de parámetros. Lo he visto antes, y esto no es así, ya que incluso cuando codifico los valores en SSMS, sigo obteniendo un rendimiento lento.

No estoy convencido. Las variables de codificación rígida en SSMS no prueban que el plan de ejecución incorrecta anterior no se compilara contra una entrada sesgada. Por favor lea Parámetros Sniffing, Embedded y RECOMPILE Options para un muy buen artículo sobre el tema. ¿Lento en la aplicación, rápido en SSMS? Comprender los misterios de rendimiento es otra excelente referencia.

Llegué a la conclusión (tal vez incorrectamente) de estos pequeños experimentos que la razón de la desaceleración se debe a cómo se configura el plan de ejecución en caché de SQL: cuando la consulta es un poco diferente, tiene que crear un nuevo plan de ejecución.

Esto se puede probar fácilmente. SET STATISTICS TIME ONle mostrará el tiempo de compilación vs. tiempo de ejecución. SQL Server: los contadores de rendimiento de estadísticas también revelarán si la compilación es un problema (francamente, me parece poco probable).

Sin embargo, hay algo similar que puede encontrar: la puerta de concesión de consulta. Leer concesión de memoria del servidor SQL entendimiento para más detalles. Si su consulta solicita una gran concesión por el momento no hay memoria disponible, tendrá que esperar, y todo se verá como 'ejecución lenta' para la aplicación. El análisis de las estadísticas de información de espera revelará si este es el caso.

Para una discusión más general sobre qué medir y qué buscar, consulte Cómo analizar el rendimiento de SQL Server


7

Esta es una pesadilla de ejecutar consultas complejas en SQL Server. Afortunadamente, no sucede tan a menudo.

Mire el plan de consulta para la consulta (cuando se ejecuta lentamente). Supongo que encontrará una unión de bucle anidado que se produce una o más veces en tablas sin índices para la unión. Esto realmente ralentiza las cosas. Para avanzar rápidamente, la forma de solucionar esto es con una pista. Agregue lo siguiente al final de la consulta:

OPTION (MERGE JOIN, HASH JOIN)

En general, esto me ha solucionado este problema en el pasado.

Lo que puede estar sucediendo es que cambios sutiles en la tabla (o en la disponibilidad de espacio temporal) hacen que la optimización de SQL prefiera un algoritmo de unión más lento. Esto puede ser bastante sutil y bastante repentino. Cuando crea una tabla temporal, el optimizador tiene más información sobre la tabla (como su tamaño), por lo que puede generar un mejor plan.


1
El plan de ejecución está utilizando una unión de bucle anidado. Sin embargo, cuando coloco la sugerencia como sugiere, aparece este error: "El procesador de consultas no pudo producir un plan de consulta debido a las sugerencias definidas en esta consulta. Vuelva a enviar la consulta sin especificar ninguna sugerencia y sin usar SET FORCEPLAN". Cuando agrego OPTION (LOOP JOIN), por supuesto, creará un plan de ejecución, pero todavía tengo un problema con que se ejecute lentamente. ¿Te has encontrado con este problema? Parece que cree que NECESITA unirse en bucle.

@Trevor. . . No, en realidad no he visto este problema. Tal vez su consulta esté haciendo algunos no equijoins (sin usar signos iguales) y el optimizador tenga que usar uniones de bucle anidadas allí.
Gordon Linoff

3

Por lo general, es un índice faltante que causa este tipo de problema.

Lo que suelo hacer es ejecutar la consulta con SQL Management Studio y habilitar 'Incluir plan de ejecución real (CTRL + M)' y averiguar qué combinación tiene el mayor porcentaje.

La aplicación no se centra en el cuello de botella, pero puede encontrarla "rápidamente" simplemente mirando el resultado.

ejemplo aquí: 48PercentForTop


2
Sin embargo, un índice no "desaparecerá" repentinamente, por lo que si bien esto puede mejorar el rendimiento, no explica el problema
Fowl

3

Recientemente experimenté este mismo problema que me llevó a esta página.

@MartinSmith estaba haciendo algo cuando recomendó actualizar sus estadísticas y explicar el plan. Me gustaría agregar que también debe intentar asegurarse de echar un vistazo a los trabajos / consultas en ejecución que pueden crear bloqueos y, por lo tanto, ralentizar el tiempo de respuesta.

En mi caso, el culpable fue la estadística de la mesa de reunión de trabajo. Por alguna razón, no se completó en la ventana que debería, y siguió ejecutándose cuando los usuarios se reanudaron. Encontré el proceso, lo eliminé y las consultas comenzaron a responder nuevamente.

Espero que esto ayude a alguien más


0

También debe verificar si se está ejecutando una copia de seguridad del servidor o algún trabajo de Archivado / indexado cuando ve un problema de rendimiento en T-SQL \ Procedimiento.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.