Uso elevado de la CPU en el servidor SQL: consultas lentas [cerrado]

11

Nuestro servidor MS SQL utiliza aproximadamente el 95% de la potencia de la CPU.

Después de reiniciar un servidor (hardware) o un reinicio del servicio SQL, el uso es del 0% y aumenta lentamente en el transcurso de 1-3 días. Dependiendo de cuánto se usa.

Cuando supera el 80%, cada consulta es extremadamente lenta.

Nuestro sitio web se ocupa de muchas consultas grandes, por lo que algunas tardan entre 45 y 60 segundos. Después de un reinicio (uso de la CPU inferior al 80%), se tarda 11-20 segundos para la misma consulta.


¿Cómo puedo arreglar esto? He leído en línea que las máscaras de afinidad pueden ajustar el uso de la CPU, pero la configuración de afinidad está desactivada. No puedo cambiarlos. ¿Es esto porque solo tengo 1 procesador?

Hay muchos trucos que hacer con las consultas en sí, pero nuestros sitios web y servicios son bastante grandes, y simplemente hay demasiado para cambiar.

La mayoría de ellos ya están bastante bien optimizados.


No puedo seguir reiniciando el servicio SQL, aunque solo demore 2 segundos, porque tenemos un servicio de alarma que permite que las personas llamen y graben un mensaje, entonces se llamará a un grupo seleccionado y escuchará el mensaje grabado.

Este equipo es utilizado por cientos de equipos de búsqueda y rescate, y si el servicio SQL se reinicia durante una alarma, terminará y la persona que lo llamó no será notificada.


He buscado por todo el lugar, pero no he encontrado nada excepto cosas sobre "Máscaras de afinidad", que no puedo cambiar.

Debe haber una manera de borrar el caché de la CPU, sin terminar las consultas actuales ... ¿verdad?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
Levi Johansen
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Paul White 9

Respuestas:

7

Esta es una posibilidad remota, pero es posible que desee echar un vistazo a su configuración de parametrización forzada. Si ve una gran cantidad de planes de consulta cuando el rendimiento es malo, sus consultas no se almacenan en caché de la manera esperada y las consultas tardan mucho tiempo en analizar el caché para ver si ya hay un plan para usar. Si borrar el caché resuelve este problema, es posible que desee considerar cambiar la configuración de parametrización forzada. Puede borrar el caché usando:

DBCC FREEPROCCACHE

Puede verificar para ver cuál es la configuración de parametrización forzada si se borra el caché trabajado por:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Probablemente esté configurado en 0, el valor predeterminado. Si lo desean, puede configurarlo como verdadero haciendo:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Esto debe hacerse primero en un entorno de desarrollo y ver si esto afecta negativamente a la base de datos de otras maneras. Se puede revertir usando:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
Drew Leffelman
fuente
55
Tenga en cuenta que liberar la memoria caché del procedimiento podría causar un gran aumento en la CPU, ya que todas las consultas ahora tendrán que volver a compilar sus planes de ejecución.
Aaron Bertrand
18

Affinity no "ajusta el uso de la CPU" (por ejemplo, en su caso hace que las CPU realicen menos trabajo), le permite apagar una CPU (quizás para que esté disponible para otra instancia en la misma máquina) o configurar una CPU para ayuda solo con E / S. Incluso si tuviera múltiples CPU, no podría usar la primera para ayudarlo con su objetivo, y es imposible para nosotros adivinar la segunda porque no sabemos qué está impulsando el uso de su CPU tan alto. Podría deberse a una indexación extremadamente pobre, recopilaciones excesivas, abundancia de UDF escalares, sacudidas de E / S, ¿quién sabe? (Y la razón por la que la E / S podría ser la causa es que si su base de datos es más grande que 3 GB, tendrá que intercambiar datos constantemente dentro y fuera de la memoria de la agrupación de almacenamiento intermedio, y esto afecta a la CPU).

El caché de la CPU, también, es un agujero de conejo que no necesita estar cayendo. Dudo mucho que su CPU tenga un rendimiento del 95% debido a problemas con el caché de su CPU.

Para ayudar a reducir la fuente de presión de la CPU, y suponiendo que esté utilizando procedimientos almacenados, puede consultar esta consulta de diagnóstico de Glenn Berry ( obtenida de aquí ): asegúrese de ejecutarla en el contexto de la base de datos correcta:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

SELECT TOP (25) 
  p.name AS [SP Name], 
  qs.total_worker_time AS [TotalWorkerTime], 
  qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], 
  qs.execution_count, 
  ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) 
    AS [Calls/Second],
  qs.total_elapsed_time, 
  qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time], 
  qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

Si no está utilizando procedimientos almacenados, este ejemplo de John Samson puede ayudar a aislar consultas ad hoc ( obtenidas de aquí ):

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

También puede echar un vistazo a sp_WhoIsActive de Adam Machanic , un procedimiento almacenado que puede analizar rápidamente todas las consultas que se ejecutan actualmente y le permite ordenarlo como desee (por ejemplo, en su caso @sort_order = '[CPU] DESC').

Sin embargo, lo primero que haría, especialmente si esto es realmente una misión crítica para los equipos de búsqueda y rescate, es comprar un mejor hardware. Debería tener más CPU y más RAM para dar servicio a su aplicación. También necesita una mejor alta disponibilidad (por ejemplo, agrupación en clúster, duplicación o grupos de disponibilidad). No hay razón para que el reinicio de una máquina física deje su aplicación completamente fuera de línea; tenemos mejores soluciones para ese problema. Y finalmente, supongo que este "servidor" solo tiene una unidad de disco espinosa. Esto significa que todas las E / S, desde el sistema operativo, los archivos de datos de SQL Server, los archivos de registro, tempdb, etc., pasan por un solo controlador y comparten la actividad de lectura / escritura en una sola unidad. Consigue más discos. Obtenga SSD si / donde pueda. Use RAID e intente extender la E / S lo más posible.

Dicho todo esto, lanzar hardware al problema no será la única parte de la solución. Debe aislar exactamente qué está causando el uso excesivo de la CPU y luego atacar esos problemas sin importar en qué hardware se encuentre.

Consulte también esta pregunta de StackOverflow para conocer otras ideas:

/programming/945063/how-do-i-find-out-what-is-hammering-my-sql-server

Aaron Bertrand
fuente
0

Las siguientes sugerencias son un "disparo en la oscuridad" porque no puedo ver el código real.

Primero es que un SP podría estar abriendo cursores y dejándolos abiertos. Lea sobre los cursores, particularmente Close y Deallocate. Alguien podría estar cerrando, pero no desasignando cursores. El comportamiento podría haber cambiado debido a la actualización, 2012 podría tratar los cursores sobrantes de manera diferente a 2008 R2.

En segundo lugar, puede haber bloqueos de tabla que no se eliminen. Nuevamente, estoy a una distancia, así que no puedo decirlo, pero sugeriría que alguien crea una tabla temporal global después de una "transacción inicial", y que no se ejecuta ninguna "transacción final" o el procedimiento almacenado falla dejando un bloqueado tabla que ocupa espacio en tempdb.

¿Estás usando WinLink por casualidad? Algo sobre esto suena vagamente familiar.

Meredith Pobre
fuente
-4

Debe tener un mecanismo de almacenamiento en caché como memcached para mejorar el rendimiento


fuente
Pero esto no cambiaría el uso de la CPU en el servidor SQL, ¿verdad? Simplemente haría que las consultas fueran más rápidas en el sitio web, y podría haber problemas si algo se cambia en una tabla mientras otra persona usa los resultados de Memcached de la misma tabla, ¿verdad?
Levi Johansen
@Levi si almacena en caché los resultados de la consulta en algún lugar del nivel medio, las consultas no llegan a la base de datos (excepto cuando necesita actualizar la caché).
Aaron Bertrand
1
Si la CPU también es alta cuando no hay nadie en el sitio web, entonces, obviamente, el almacenamiento en caché de cosas a nivel web no ayudaría. Memcached es una gran herramienta, pero no un reemplazo para que una persona competente se siente y descubra qué está haciendo el servidor cuando supuestamente no debería hacer nada.
TomTom