sql >> Base de Datos >  >> RDS >> Sqlserver

Solución de problemas de consultas de ejecución prolongada en MS SQL Server

Prefacio

Hay un sistema de información que yo administro. El sistema consta de los siguientes componentes:

1. Base de datos de MS SQL Server
2. Aplicación de servidor
3. Aplicaciones cliente

Estos sistemas de información están instalados en varios objetos. El sistema de información es utilizado activamente las 24 horas del día por 2 a 20 usuarios a la vez en cada objeto. Por lo tanto, no puede realizar el mantenimiento de rutina todo a la vez. Por lo tanto, tengo que "difundir" la desfragmentación de índices de SQL Server a lo largo del día, en lugar de desfragmentar todos los índices fragmentados necesarios de una sola vez. Esto también se aplica a otras operaciones.

La propiedad de actualización automática de estadísticas se establece en las propiedades de la base de datos. Además, las estadísticas se actualizan en el índice desfragmentado.

Problema

Hace aproximadamente un año, me encontré con el siguiente problema:

De vez en cuando, todas las consultas se ejecutaban lentamente. En particular, el tiempo de retraso fue aleatorio. Sucedió en cada objeto en un día aleatorio. Además, cuando comencé a analizar con qué frecuencia ocurren los retrasos (usando el generador de perfiles), descubrí que ocurren todos los días en un momento aleatorio. Los usuarios simplemente no siempre les prestan atención, sino que los toman como el único retraso aleatorio, y luego el sistema vuelve a funcionar rápidamente.

Resolviendo el problema

He revisado todas las consultas de ejecución lenta. Lo más extraño fue que todas las consultas se ejecutaban lentamente en un momento aleatorio, incluso las más simples, como extraer el último registro de una tabla con varios miles de filas.

Además, realicé los siguientes pasos:

1. Analicé los registros de MS SQL Server y Windows Server, pero no pude encontrar la causa de los retrasos.
2. Analicé índices (fragmentación, etc.), agregué los que faltaban y eliminé los que no se usaban.
3. Analicé las consultas; se mejoraron algunas consultas.
4. Analicé las tareas en el Agente SQL y no pude asociar las tareas con el problema de retraso.
5. Analicé las tareas en el Programador de tareas y no pude asociar las tareas con el problema de retraso.
6. Profiler mostró los resultados, pero no la causa de los retrasos.
7. Realicé una verificación de interbloqueos:no se revelaron bloqueos prolongados.

Como resultado, pasé más de 3 meses en la búsqueda infructuosa del motivo de consultas ocasionales lentas. Sin embargo, revelé un hecho interesante:en lugar del indicador de ejecución del trabajador, el indicador de espera transcurrida aumentó para todas las consultas. Este hecho me dio la idea de que algo anda mal con los discos. Los revisé, todo estaba bien.

Solución

Para mi sorpresa, accidentalmente revelé que cuando una consulta se ejecutaba lentamente en la aplicación, se ejecutaba rápidamente en SSMS. Un artículo ayudó a resolver el problema (al menos sugirió la idea).

Un párrafo del artículo:

En la práctica, la opción SET más importante es ARITHABORT, porque el valor predeterminado de esta opción es diferente para las aplicaciones y para SQL Server Management Studio. Esto explica por qué puede detectar una consulta de ejecución lenta en su aplicación y luego obtener una buena velocidad ejecutándola en SSMS. La aplicación utiliza un plan que se creó para un conjunto de valores que difiere de los valores correctos reales. Mientras que si ejecuta la consulta en SSMS, lo más probable es que la caché aún no tenga un plan de ejecución para ARITHABORT ON y, por lo tanto, SQL Server creará un plan para sus valores actuales.

La diferencia en la ejecución se debió al parámetro SET ARITHABORT. Para todas las consultas ejecutadas en SSMS, esta opción está habilitada y para consultas desde el exterior (desde aplicaciones), deshabilitada. No se puede habilitar ni siquiera con una simple consulta de aplicaciones:

SET ARITHABORT ON;

Siguió una idea loca:borrar el caché de procedimiento en el momento de colgar.

Para la verificación manual posterior, debo escribir la siguiente declaración antes de la consulta en SSMS:

SET ARITHABORT OFF;

Así simularemos el funcionamiento de la aplicación. Cuando la consulta se había estado ejecutando durante mucho tiempo, borré el caché de procedimiento. Y esto siempre ayudó. Antes de borrar la memoria caché de procedimiento, la consulta podría ejecutarse hasta 20-30 segundos y, después, 0 segundos.

Después de eso, realicé otro experimento:limpié todo el caché de procedimientos para toda la base de datos cada hora a través del Agente SQL:

--cleaning the cache by database id
DBCC FLUSHPROCINDB (@db_id);

Después de eso, todas las consultas se ejecutaron muy rápidamente (menos de 0,05 segundos). Solo hubo algunas ocurrencias de hasta 5-10 segundos de ejecución, pero los usuarios no notaron ningún bloqueo. Además, actualizar las estadísticas no mejoró los resultados, así que deshabilité la actualización de estadísticas.

Después de unos meses más de estudio, descubrí que se producen bloqueos ocasionales cuando el caché consume todo en el servidor y no queda espacio libre o hay memoria libre, pero menos de 1 GB de RAM o el servicio MS SQL Server. ocupa toda la memoria RAM asignada (a través del Administrador de tareas). Pero el segundo evento ocurrió solo dos veces en todo el estudio.

El hecho es que, literalmente, todo está escrito en el caché, mientras que el caché no siempre se libera a tiempo. El problema con el caché se resolvió usando el programa EmptyStandbyList.exe.

Configuré esta aplicación a través del Programador de tareas para que se ejecute 1 vez cada hora. Después de todo el trabajo realizado, no hay consultas colgadas en todos los objetos desde hace más de medio año.

Lo único que no está claro son los raros casos en que una consulta se cuelga durante 5 a 10 segundos una vez al mes en un día y hora aleatorios. Hubo 4 casos de este tipo y solo en dos objetos durante medio año cuando el servicio MS SQL Server ocupa toda la memoria asignada durante un breve período de tiempo.

Básicamente, no hay necesidad de profundizar más, ya que los usuarios no notan ningún problema y todo funciona bien, pero si alguien tiene alguna idea, le agradeceré que la comparta.

Este artículo fue escrito para ayudar a aquellos que se encuentran con este tipo de problemas, ya que no encontré una respuesta completa en Internet y dediqué mucho tiempo a estudiar el problema y encontrar la solución.

Véase también:

  1. Implementación del indicador de rendimiento de SQL Server para consultas, procedimientos almacenados y disparadores
  2. Automatización de la desfragmentación de índices en la base de datos de MS SQL Server


Herramienta útil:

dbForge Query Builder para SQL Server:permite a los usuarios crear consultas SQL complejas rápida y fácilmente a través de una interfaz visual intuitiva sin necesidad de escribir código manualmente.