¿Por qué mi consulta de repente es más lenta que ayer?

76

[Saludos]

(marque uno)

[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,

Tengo un (marque todo lo que corresponda)

[ ] query [ ] stored procedure [ ] database thing maybe  

que funcionaba bien (si corresponde)

[ ] yesterday [ ] in recent memory [ ] at some point 

pero de repente es más lento ahora.

Ya lo he verificado para asegurarme de que no esté bloqueado y que no sea víctima de alguna tarea de mantenimiento, informe u otro proceso fuera de banda de larga ejecución.

¿Cuál es el problema, qué debo hacer y qué información puedo proporcionar para obtener ayuda?

[*Insert appropriate closing remarks*]
Erik Darling
fuente

Respuestas:

88

Estimado [su nombre aquí]!

¡Oh no, lamento escuchar eso! Comencemos con algunos conceptos básicos para arreglarlo en un santiamén.

La cosa con la que te encuentras se llama Parameter Sniffing

Es una forma de resolver el extraño problema. El nombre sale de la lengua. Como la palabra alemana para ardilla.

Y generalmente es tu amigo.

Cuando una consulta llega a su servidor, se debe compilar un plan. Para ahorrar tiempo y recursos más adelante, se almacena en caché un plan de ejecución basado en las filas estimadas que harán que su código procese y regrese.

La forma más fácil de imaginar que esto va mal es imaginar un procedimiento almacenado que necesite contar cosas de dos poblaciones asimétricas.

Por ejemplo:

  • Personas que usan camisas CrossFit que no están lesionadas: Zero

  • Personas que usan camisas CrossFit que hacen una mueca cuando hacen una mueca: todos

Obviamente, una ejecución de ese código tendría que hacer mucho más trabajo que otra, y los planes de consulta que desearía realizar cantidades de trabajo totalmente diferentes se verían totalmente diferentes.

¿A qué me enfrento?

Este es un problema realmente difícil de encontrar, probar y solucionar.

  • Es difícil de encontrar porque no sucede constantemente
  • Es difícil de probar porque necesita saber qué parámetros causan diferentes planes
  • Es difícil de solucionar porque a veces requiere consultas y ajuste de índice
  • Es difícil de solucionar porque es posible que no pueda cambiar consultas o índices
  • Es difícil de solucionar porque incluso si cambia las consultas o los índices, aún podría volver

Arreglos rápidos

A veces, todo lo que necesitas es un poco de claridad. O más bien, su caché del plan lo hace.

Si es un procedimiento almacenado

Intenta correr EXEC sys.sp_recompile @objname = N'schema.procname'. Eso hará que el procedimiento recompile un nuevo plan la próxima vez que se ejecute.

Lo que esto no solucionará:

  • Procesos que actualmente lo ejecutan.

Lo que esto no garantiza:

  • El siguiente proceso que se ejecuta después de la recompilación utilizará un parámetro que le dará un buen plan.

También puede apuntar sp_recompilea una tabla o vista, pero tenga en cuenta que todo el código que toque esa tabla o vista se recompilará. Esto podría hacer que el problema sea mucho más difícil.

Si es una consulta parametrizada

Tu trabajo es un poco más difícil. Deberá localizar el controlador SQL. No desea liberar todo el caché del plan; al igual que si se usa sp_recompilecontra una tabla o vista, podría desencadenar (ja, ja, ja) un montón de consecuencias no deseadas.

La forma más fácil de resolver ese comando es ejecutar sp_BlitzWho *! Hay una columna llamada "sniffing de parámetros fijos" que tiene un comando para eliminar un solo plan del caché. Sin embargo, esto tiene los mismos inconvenientes que la recompilación.

Lo que esto no solucionará:

  • Procesos que actualmente lo ejecutan.

Lo que esto no garantiza:

  • El siguiente proceso que se ejecuta después de la recompilación utilizará un parámetro que le dará un buen plan.

¡Todavía necesito ayuda!

Vamos a necesitar lo siguiente:

  • El buen plan de consulta, si es posible
  • El mal plan de consulta
  • Los parámetros utilizados
  • La consulta en cuestión
  • Definiciones de tabla e índice

Obtener los planes de consulta y consulta

Si la consulta se está ejecutando, puede usar sp_BlitzWho * o sp_WhoIsActive para capturar las consultas que se están ejecutando actualmente.

EXEC sp_BlitzWho;

EXEC sp_WhoIsActive @get_plans = 1;

NUECES

Si la consulta no se está ejecutando actualmente, puede verificarla en la caché del plan, usando sp_BlitzCache *.

Si tiene SQL Server 2016+ y tiene activado el Almacén de consultas, puede usar sp_BlitzQueryStore *.

EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';

EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';

Esto lo ayudará a rastrear las versiones en caché de su Procedimiento almacenado. Si solo se trata de un código parametrizado, su búsqueda es un poco más difícil. Sin embargo, esto puede ayudar:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

Debería ver una salida bastante similar de cualquiera de esos. Una vez más, el plan de consulta que invita a la columna de clic azul es tu amigo.

NUECES

La forma más fácil de compartir planes es usar Pegar el plan * o volcar el XML en pastebin. Para obtener eso, haga clic en cualquiera de esas atractivas columnas azules clicky. Su plan de consulta debería aparecer en una nueva pestaña SSMS.

NUECES

Si le preocupa compartir el código y la consulta de su empresa, puede usar la herramienta gratuita Plan Explorer de Sentry One para anonimizar su plan. Tenga en cuenta que esto hace que obtener ayuda sea más difícil: el código anónimo es mucho más difícil de leer y resolver.

Todas estas herramientas de las que hablamos deberían devolver el Texto de consulta. No necesitas hacer nada más aquí.

Obtener los parámetros es un poco más difícil. Si está utilizando Plan Explorer , hay una pestaña en la parte inferior que los enumera todos por usted.

NUECES

Si está utilizando sp_BlitzCache *, hay una columna en la que se puede hacer clic que le proporciona la instrucción de ejecución para los procedimientos almacenados.

NUECES

Obtener las definiciones de tabla e índice

Puede hacer clic con el botón derecho en SSMS para escribir las cosas.

NUECES

Si desea obtener todo de una vez, sp_BlitzIndex * puede ayudarlo si lo apunta directamente a una mesa.

EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
                       @SchemaName = 'dbo',
                       @TableName = 'Users';

Esto le dará la definición de la tabla (aunque no como una declaración de creación) y creará declaraciones para todos sus índices.

Recopilar y agregar esta información a su pregunta debería brindarle a la gente suficiente información para ayudarlo o orientarlo en la dirección correcta.

¡Quiero hacerlo yo mismo!

Bueno, genial Estoy feliz por ti. Eres un loco.

Hay muchas maneras en que las personas piensan que "arreglan" la detección de parámetros:

Pero estos realmente solo deshabilitan el rastreo de parámetros de diferentes maneras. Eso no quiere decir que no puedan resolver el problema, simplemente no llegan a la causa raíz.

Eso se debe a que llegar a la causa raíz suele ser un poco difícil. Tienes que buscar esos molestos "problemas de calidad del plan".

Comenzando con los planes rápido versus lento, busque diferencias como:

  • Índices utilizados
  • Orden de unión
  • Serie vs Paralelo

También busque diferentes operadores que hagan que su código sea sensible al rastreo de parámetros:

  • Búsquedas
  • Ordena
  • Tipo de unión
  • Concesiones de memoria (y por extensión, derrames)
  • Carretes

No se deje envolver demasiado en la búsqueda contra el escaneo, la fragmentación del índice ni ninguna de las cosas de culto de la carga que la gente dobla y habla.

Por lo general, hay un problema de indexación bastante básico. A veces el código necesita una pequeña reescritura.

Si desea obtener más información sobre la detección de parámetros:

Si estás leyendo esto y crees que me perdí un enlace o una herramienta útil, deja un comentario. Haré todo lo posible para mantener esto actualizado.


Erik Darling
fuente
28

La detección de parámetros no es la única causa posible del rendimiento variable de una consulta. Cualquiera de las siguientes razones comunes puede mostrar los mismos síntomas:

  1. Distribución de datos / volumen cambiado, cruzando un punto de inflexión del árbol de búsqueda del optimizador
  2. Los índices / archivos se fragmentaron
  3. Las estadísticas se han actualizado / agregado / eliminado o se han vuelto obsoletas y engañosas debido a cambios en los datos
  4. La utilización de la memoria de Windows cambió
  5. Los registros de transacciones están llenos y no se truncan, lo que provoca la expansión repetida de archivos físicos
  6. Esquema cambiado: índice / vista indexada / columna / restricción agregada, modificada o descartada, tipo de datos cambiado, etc.
  7. La configuración de la marca de seguimiento ha cambiado
  8. Se aplicó la actualización de Windows
  9. La configuración de la base de datos o del servidor cambió
  10. El nivel de CU del servidor cambió
  11. La configuración de la sesión de la aplicación cliente cambió

Los elementos 6 a 11 de esta lista solo pueden suceder después de que se haya tomado alguna acción explícita. Supongo que querías excluirlos, pero muchas veces el que está experimentando el desafío no es consciente de que alguien más realizó cambios, y vale la pena verificarlo antes de emprender el camino de borrar las entradas de caché del plan.

SQLRaptor
fuente
1
Gracias por la edición de Paul. @sp_BlitzErik: no era mi intención proporcionar asesoramiento sobre temas específicos, solo para crear conciencia de que existen y que valdría la pena echarle un vistazo. Esto de ninguna manera tiene la intención de disminuir de tu gran publicación. Trataste el análisis de parámetros en profundidad, profesionalmente y con buen humor. Disfruté leyéndolo. Solo quiero asegurarme de que si alguien aquí visita esta publicación, siguiendo el título pegadizo, él / ella esté al tanto de las posibles causas alternativas. En mi humilde opinión, agrega valor a su publicación, pero si aún desea que lo elimine, hágamelo saber.
SQLRaptor
No, en absoluto. Nunca le pediría a alguien que elimine una respuesta que no sea incorrecta o dañina. Todavía creo que podrías agregar algunos detalles, pero eso depende de ti.
Erik Darling
10

Solo para agregar a las respuestas existentes en caso de que no ayudaran, cuando "repentinamente" sus consultas se comporten de manera diferente al día siguiente, verifique:

  • ¿Ha cambiado el esquema de las tablas usadas desde la última vez? En el caso de SSMS, puede hacer clic con el botón derecho en el servidor en el Explorador de objetos y elegir Reports → Standard Reports → Schema Changes History.
  • ¿El recuento de artículos aumentó dramáticamente? Tal vez su consulta sea mucho más lenta cuando haya muchos datos en las tablas usadas.
  • ¿Alguien más está utilizando la base de datos al mismo tiempo que usted? Tal vez elija franjas horarias donde no interfieran con el trabajo del otro.
  • ¿Cómo se ven las estadísticas del sistema? Tal vez el servidor se está ejecutando en caliente y está acelerando la CPU o los discos duros se están quedando sin espacio o intercambio. Tal vez hay otro problema de hardware como un incendio o una inundación en la sala de servidores.
usuario1306322
fuente
7

Otra posibilidad es que su equipo de infraestructura esté utilizando herramientas como vMotion en VMware y la VM que admite su instancia de SQL se traslade sin problemas de un host a otro sin que el DBA lo sepa.

Este es un problema real cuando su Infraestructura está externalizada ... Estoy teniendo una verdadera pesadilla con ella.

pacreely
fuente