web-dev-qa-db-fra.com

Utilisation élevée du processeur sur le serveur SQL - Requêtes lentes

Notre serveur MS SQL utilise environ 95% de la puissance du processeur.

Après un redémarrage du serveur (matériel) ou un redémarrage du service SQL, l'utilisation est de 0% et augmente lentement en 1 à 3 jours. Selon la quantité utilisée.

Quand il dépasse 80%, chaque requête est extrêmement lente.

Notre site Web traite de nombreuses requêtes importantes, donc certaines d'entre elles prennent 45 à 60 secondes. Après un redémarrage (utilisation du processeur inférieure à 80%), il faut 11-20 secondes pour la même requête.


Comment puis-je réparer cela? J'ai lu en ligne que les masques d'affinité peuvent ajuster l'utilisation du processeur, mais les paramètres d'affinité sont désactivés. Je ne peux pas les changer. Est-ce parce que je n'ai qu'un seul processeur?

Il y a beaucoup d'astuces à faire avec les requêtes elles-mêmes, mais nos sites Web et services sont assez grands et il y a tout simplement trop de choses à changer.

La plupart d'entre eux sont déjà assez bien optimisés.


Je ne peux pas continuer à redémarrer le service SQL, même si cela ne prend que 2 secondes, car nous avons un service d'alarme qui permet aux gens d'appeler et d'enregistrer un message, un groupe sélectionné sera alors appelé et entendra le message enregistré.

Ce système est utilisé par des centaines d'équipes de recherche et sauvetage, et si le service SQL redémarre pendant une alarme, il se terminera et la personne qui l'a appelé ne sera pas avertie.


J'ai cherché partout, mais je n'ai rien trouvé à part des trucs sur "Affinity Masks", que je ne peux pas changer.

Il doit y avoir un moyen de vider le cache CPU, sans mettre fin aux requêtes en cours ... non?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
11
Levi Johansen

C'est un long plan, mais vous voudrez peut-être jeter un œil à votre réglage de paramétrage forcé. Si vous voyez un grand nombre de plans de requête lorsque les performances sont mauvaises, vos requêtes ne sont pas mises en cache comme vous vous y attendez et les requêtes mettent beaucoup de temps à parcourir le cache pour voir s'il est déjà prévu de les utiliser. Si l'effacement du cache résout ce problème, vous pouvez envisager de modifier le paramètre de paramétrage forcé. Vous pouvez vider le cache en utilisant:

DBCC FREEPROCCACHE

Vous pouvez vérifier quel est le paramètre de paramétrage forcé si l'effacement du cache a fonctionné par:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Il est probablement défini sur 0, la valeur par défaut. S'ils le souhaitent, vous pouvez définir cela sur true en faisant:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Cela doit être fait dans un environnement de développement en premier et voir si cela a un impact négatif sur la base de données d'autres manières. Il peut être annulé en utilisant:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
7
Drew Leffelman

Affinity ne "règle pas l'utilisation du processeur" (par exemple, dans votre cas, les processeurs effectuent moins de travail), il vous permet soit d'éteindre un processeur (peut-être pour le rendre disponible à une autre instance sur la même machine), soit de définir un processeur sur aide aux E/S uniquement. Même si vous aviez plusieurs processeurs, vous ne seriez pas en mesure d'utiliser le premier pour vous aider à atteindre votre objectif, et il nous est impossible de deviner le dernier car nous ne savons pas ce qui motive votre utilisation du processeur. Cela pourrait être dû à une indexation extrêmement médiocre, à des compilations excessives, à une abondance d'UDF scalaires, à un thrash d'E/S, qui sait? (Et la raison pour laquelle les E/S pourraient être la cause est que si votre base de données est supérieure à 3 Go environ, elle devra constamment échanger des données dans et hors de la mémoire du pool de mémoire tampon, et cela pèse lourd sur le processeur.)

Le cache du processeur est également un trou de lapin que vous n'avez pas besoin de descendre. Je doute fortement que votre CPU bat à 95% à cause de problèmes avec votre cache CPU.

Pour aider à réduire la source de pression du processeur et en supposant que vous utilisez des procédures stockées, vous pouvez consulter cette requête de diagnostic de Glenn Berry ( provenant d'ici ) - assurez-vous de l'exécuter dans le contexte de la bonne base de données:

-- 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 vous n'utilisez pas de procédures stockées, cet exemple de John Samson peut aider à isoler les requêtes ad hoc ( provenant d'ici ):

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);

Vous pouvez également jeter un œil à sp_WhoIsActive d'Adam Machanic, une procédure stockée qui peut rapidement analyser toutes les requêtes en cours d'exécution et vous permettre de les trier comme vous le souhaitez (par exemple dans votre cas @sort_order = '[CPU] DESC').

Cependant, la première chose que je ferais - en particulier si c'est vraiment essentiel pour les équipes de recherche et de sauvetage - est d'acheter un meilleur matériel. Vous devriez avoir plus de CPU et plus RAM pour entretenir votre application. Vous avez aussi absolument besoin d'une meilleure haute disponibilité (par exemple le clustering, la mise en miroir ou les groupes de disponibilité). Il n'y a aucune raison qu'un redémarrage d'une machine physique devrait mettre votre application complètement hors ligne - nous avons de meilleures solutions pour ce problème. Et enfin, je suppose que ce "serveur" n'a qu'un seul lecteur de disque rotatif. Cela signifie que toutes les E/S - du système d'exploitation, des fichiers de données SQL Server, connectez-vous fichiers, tempdb, etc. passent tous par un seul contrôleur et partagent l'activité de lecture/écriture sur un seul lecteur. Obtenez plus de disques. Obtenez des SSD si/où vous le pouvez. Utilisez RAID et essayez de répartir les E/S autant que possible .

Cela dit, jeter du matériel sur le problème ne sera pas la seule partie du correctif. Vous devez isoler exactement ce qui cause une utilisation excessive du processeur, puis attaquer ces problèmes, quel que soit le matériel sur lequel vous vous trouvez.

Consultez également cette question StackOverflow pour d'autres idées:

https://stackoverflow.com/questions/945063/how-do-i-find-out-what-is-hammering-my-sql-server

18
Aaron Bertrand

Les suggestions suivantes sont un "tir dans le noir" car je ne vois pas le code réel.

Premièrement, un SP peut ouvrir des curseurs et les laisser ouverts. Lisez sur les curseurs, en particulier Fermer et Désallouer. Quelqu'un peut fermer, mais pas désallouer les curseurs. Le comportement peut avoir changé en raison mise à niveau, 2012 pourrait traiter les curseurs restants différemment de 2008 R2.

Deuxièmement, il peut y avoir des verrous de table qui ne sont pas effacés. Encore une fois, je suis à distance, donc je ne peux pas le dire, mais cela suggérerait que quelqu'un crée une table temporaire globale après une `` transaction de début '', et qu'aucune `` transaction de fin '' ne soit exécutée ou la procédure stockée échoue en laissant un verrouillé table occupant l'espace dans tempdb.

Utilisez-vous WinLink par hasard? Quelque chose à ce sujet semble vaguement familier.

0
Meredith Poor