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

11

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 gros, 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 du processeur, 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
Levi Johansen
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Paul White 9

Réponses:

7

C'est un long plan, mais vous voudrez peut-être jeter un œil à votre paramètre 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 d'abord 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;
Drew Leffelman
la source
5
Notez que la libération du cache de procédures pourrait en fait provoquer une énorme pointe de CPU - car toutes les requêtes devront désormais recompiler leurs plans d'exécution.
Aaron Bertrand
18

Affinity ne "règle pas l'utilisation du CPU" (par exemple, dans votre cas, les CPU effectuent moins de travail), il vous permet soit d'éteindre un CPU (peut-être pour le rendre disponible à une autre instance sur la même machine), soit de définir un CPU 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 fait que votre utilisation du processeur est si élevée. 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% en raison de problèmes avec le cache de votre 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 oeil à Adam de Machanic sp_WhoIsActive , une procédure stockée qui permet d' analyser rapidement toutes les requêtes en cours d' exécution, et vous permettent de trier cependant que vous voulez (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 de RAM pour gérer votre application. Vous avez également absolument besoin d'une meilleure haute disponibilité (par exemple, mise en cluster, mise en miroir ou 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, des fichiers journaux, tempdb, etc. passent toutes 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:

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

Aaron Bertrand
la source
0

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. Renseignez-vous sur les curseurs, en particulier sur Fermer et désallouer. Il se peut que quelqu'un ferme, mais ne désalloue pas les curseurs. Le comportement peut avoir changé en raison de la mise à niveau, 2012 peut 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 que 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.

Meredith Poor
la source
-4

Vous devriez avoir un mécanisme de mise en cache comme memcached pour améliorer les performances


la source
Mais cela ne changerait pas l'utilisation du processeur sur le serveur SQL, non? Cela rendrait les requêtes plus rapides sur le site Web, et il pourrait y avoir des problèmes si quelque chose est changé dans une table tandis que quelqu'un d'autre utilise les résultats memcached de la même table, non?
Levi Johansen
@Levi si vous mettez en cache les résultats de la requête quelque part dans le niveau intermédiaire, les requêtes n'atteignent pas la base de données (sauf lorsque vous devez actualiser le cache).
Aaron Bertrand
1
Si le processeur est également élevé lorsque personne n'est sur le site Web, il est évident que la mise en cache de choses au niveau du Web n'aiderait pas. Memcached est un excellent outil, mais ne remplace pas une personne compétente pour s'asseoir et découvrir ce que fait le serveur alors qu'il ne devrait rien faire.
TomTom