Hohe CPU-Auslastung auf SQL Server - Langsame Abfragen [geschlossen]

11

Unser MS SQL Server verbraucht ca. 95% der CPU-Leistung.

Nach einem Neustart des Servers (Hardware) oder eines Neustarts des SQL-Dienstes beträgt die Auslastung 0% und steigt im Laufe von 1-3 Tagen langsam an. Abhängig davon, wie viel es verwendet wird.

Wenn es über 80% ist, ist jede Abfrage extrem langsam.

Unsere Website befasst sich mit vielen großen Fragen, von denen einige 45-60 Sekunden dauern. Nach einem Neustart (CPU-Auslastung weniger als 80%) dauert es für dieselbe Abfrage 11 bis 20 Sekunden.


Wie kann ich das beheben? Ich habe online gelesen, dass Affinitätsmasken die CPU-Auslastung anpassen können, aber die Affinitätseinstellungen sind deaktiviert. Ich kann sie nicht ändern. Liegt das daran, dass ich nur 1 Prozessor habe?

Es gibt viele Tricks, die mit den Abfragen selbst zu tun haben, aber unsere Websites und Dienste sind ziemlich groß und es gibt einfach zu viel, um sie zu ändern.

Die meisten von ihnen sind bereits ziemlich gut optimiert.


Ich kann den SQL-Dienst nicht weiter neu starten, obwohl dies nur 2 Sekunden dauert, da wir einen Alarmdienst haben, mit dem Benutzer eine Nachricht anrufen und aufzeichnen können. Eine ausgewählte Gruppe wird dann angerufen und hört die aufgezeichnete Nachricht.

Dieses System wird von Hunderten von Such- und Rettungsteams verwendet. Wenn der SQL-Dienst während eines Alarms neu gestartet wird, wird er beendet und die Person, die ihn angerufen hat, wird nicht benachrichtigt.


Ich habe überall gesucht, aber nichts gefunden, außer Sachen über "Affinity Masks", die ich nicht ändern kann.

Es muss eine Möglichkeit geben, den CPU-Cache zu leeren, ohne aktuelle Abfragen zu beenden ... richtig?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
Levi Johansen
quelle
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Paul White 9

Antworten:

7

Dies ist ein langer Weg, aber vielleicht möchten Sie einen Blick auf Ihre Einstellung für die erzwungene Parametrisierung werfen. Wenn Sie bei schlechter Leistung eine große Anzahl von Abfrageplänen sehen, werden Ihre Abfragen nicht wie erwartet zwischengespeichert, und es dauert lange, bis die Abfragen den Cache durchsucht haben, um festzustellen, ob bereits ein Plan vorhanden ist. Wenn das Löschen des Caches dieses Problem löst, sollten Sie die Einstellung der erzwungenen Parametrisierung ändern. Sie können den Cache löschen mit:

DBCC FREEPROCCACHE

Sie können überprüfen, wie die Einstellung für die erzwungene Parametrisierung lautet, wenn Sie den Cache löschen, der funktioniert von:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

Dies ist wahrscheinlich die Standardeinstellung 0. Wenn sie es wünschen, können Sie dies auf wahr setzen, indem Sie Folgendes tun:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

Dies sollte zuerst in einer Entwicklungsumgebung erfolgen und prüfen, ob sich dies auf andere Weise negativ auf die Datenbank auswirkt. Es kann zurückgesetzt werden mit:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
Drew Leffelman
quelle
5
Beachten Sie, dass das Freigeben des Prozedurcaches tatsächlich zu einem enormen Anstieg der CPU führen kann, da alle Abfragen jetzt ihre Ausführungspläne neu kompilieren müssen.
Aaron Bertrand
18

Affinity "passt die CPU-Auslastung nicht an" (z. B. in Ihrem Fall die CPUs weniger arbeiten lassen), sondern ermöglicht es Ihnen, entweder eine CPU auszuschalten (möglicherweise, um sie einer anderen Instanz auf demselben Computer zur Verfügung zu stellen) oder eine CPU auf einzustellen Hilfe nur mit E / A. Selbst wenn Sie mehrere CPUs hätten, könnten Sie erstere nicht verwenden, um Ihr Ziel zu erreichen, und wir können letztere nicht erraten, da wir nicht wissen, was Ihre CPU-Auslastung so hoch treibt. Es könnte an einer extrem schlechten Indizierung, übermäßigen Kompilierungen, einer Fülle skalarer UDFs und E / A-Thrashing liegen, wer weiß? (Und der Grund, warum E / A die Ursache sein könnte, ist, dass Ihre Datenbank, wenn sie größer als 3 GB ist, ständig Daten in den Pufferpoolspeicher und aus diesem heraus austauschen muss, was die CPU belastet.)

Der CPU-Cache ist auch ein Kaninchenbau, den Sie nicht herunterfahren müssen. Ich bezweifle sehr, dass Ihre CPU aufgrund von Problemen mit Ihrem CPU-Cache zu 95% überlastet ist.

Um die Quelle des CPU-Drucks einzugrenzen und davon auszugehen, dass Sie gespeicherte Prozeduren verwenden, können Sie sich diese Diagnoseabfrage von Glenn Berry ( von hier bezogen ) ansehen. Stellen Sie sicher, dass Sie sie im Kontext der richtigen Datenbank ausführen:

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

Wenn Sie keine gespeicherten Prozeduren verwenden, kann dieses Beispiel von John Samson helfen, Ad-hoc-Abfragen zu isolieren ( von hier bezogen ):

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

Sie können sich auch Adam Machanics sp_WhoIsActive ansehen , eine gespeicherte Prozedur, mit der alle aktuell ausgeführten Abfragen schnell analysiert und sortiert werden können, wie Sie möchten (z. B. in Ihrem Fall @sort_order = '[CPU] DESC').

Das erste, was ich tun würde - insbesondere wenn dies für Such- und Rettungsteams wirklich geschäftskritisch ist - ist, bessere Hardware zu kaufen. Sie sollten mehr CPUs und mehr RAM haben, um Ihre Anwendung zu warten. Sie benötigen außerdem unbedingt eine bessere Hochverfügbarkeit (z. B. Clustering, Spiegelung oder Verfügbarkeitsgruppen). Es gibt keinen Grund, warum ein Neustart eines physischen Computers Ihre Anwendung vollständig offline schalten sollte - wir haben bessere Lösungen für dieses Problem. Und schließlich gehe ich davon aus, dass dieser "Server" nur ein Spinny-Laufwerk hat. Dies bedeutet, dass alle E / A - vom Betriebssystem, von SQL Server-Datendateien, Protokolldateien, Tempdb usw. - einen einzigen Controller durchlaufen und Lese- / Schreibaktivitäten auf einem einzigen Laufwerk gemeinsam nutzen. Holen Sie sich mehr Festplatten. Holen Sie sich SSDs, wenn / wo Sie können. Verwenden Sie RAID und versuchen Sie, die E / A so weit wie möglich zu verteilen.

Trotzdem wird das Werfen von Hardware auf das Problem nicht der einzige Teil der Lösung sein. Sie müssen genau isolieren, was zu einer übermäßigen CPU-Auslastung führt, und diese Probleme dann angreifen, unabhängig davon, auf welcher Hardware Sie sich befinden.

In dieser StackOverflow-Frage finden Sie auch einige andere Ideen:

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

Aaron Bertrand
quelle
0

Die folgenden Vorschläge sind ein "Schuss im Dunkeln", da ich den tatsächlichen Code nicht sehen kann.

Erstens kann ein SP Cursor öffnen und offen lassen. Informieren Sie sich über Cursor, insbesondere Schließen und Freigeben. Jemand könnte schließen, aber keine Cursor freigeben. Das Verhalten hat sich möglicherweise aufgrund des Upgrades geändert. 2012 werden übrig gebliebene Cursor möglicherweise anders behandelt als 2008 R2.

Zweitens kann es Tabellensperren geben, die nicht gelöscht werden. Auch hier bin ich in einiger Entfernung, daher kann ich nicht sagen, aber es würde darauf hindeuten, dass jemand nach einer 'Starttransaktion' eine globale temporäre Tabelle erstellt und entweder keine 'Endtransaktion' ausgeführt wird oder die gespeicherte Prozedur fehlschlägt und eine gesperrte zurücklässt Tabelle belegt Platz in Tempdb.

Verwenden Sie WinLink zufällig? Etwas daran klingt vage vertraut.

Meredith Arm
quelle
-4

Sie sollten über einen Caching-Mechanismus wie memcached verfügen, um die Leistung zu verbessern


quelle
Dies würde aber die CPU-Auslastung auf dem SQL-Server nicht ändern, oder? Es würde nur dazu führen, dass die Abfragen auf der Website schneller ablaufen, und es könnte Probleme geben, wenn etwas in einer Tabelle geändert wird, während jemand anderes zwischengespeicherte Ergebnisse aus derselben Tabelle verwendet, oder?
Levi Johansen
@Levi Wenn Sie die Abfrageergebnisse irgendwo in der mittleren Ebene zwischenspeichern, gelangen die Abfragen nicht in die Datenbank (außer wenn Sie den Cache aktualisieren müssen).
Aaron Bertrand
1
Wenn die CPU auch hoch ist, wenn sich niemand auf der Website befindet, würde das Zwischenspeichern von Inhalten auf Web-Ebene ganz offensichtlich nicht helfen. Memcached ist ein großartiges Tool, aber kein Ersatz für eine kompetente Person, die sich hinsetzt und herausfindet, was der Server tut, wenn er angeblich nichts tun soll.
TomTom