SQL Server unter Last langsam: CPU und Wartezeiten prüfen
Ein Bericht läuft, mehrere Benutzer öffnen gleichzeitig ihre Auftragslisten und plötzlich dauert auch das Speichern länger. Wenn SQL Server unter Last langsam wird, kann mehr Arbeit ankommen, jeder Aufruf aufwendiger geworden sein oder ein Teil der Arbeit andere Vorgänge aufhalten.
Dieser Diagnoseweg ist Teil unseres Ratgebers SQL Server Performance. Wenn Sie noch nicht wissen, welcher Weg zu Ihrem Problem passt, beginnen Sie dort.
Der erste Prüfauftrag lautet: Was verändert sich zwischen dem ruhigen und dem langsamen Zeitraum – Aufrufmenge, Aufwand je Aufruf oder Wartezeit?
Schritt 1: Einen ruhigen und einen langsamen Zeitraum vergleichen
Wählen Sie zwei gleich lange Zeitfenster, die Sie anhand vorhandener Daten vergleichen können. Notieren Sie Beginn, Ende und betroffene Aufgaben. Verwenden Sie in Anwendung, Betriebssystem und SQL Server dieselbe Zeitbasis.
Erfassen Sie für beide Zeitfenster:
| Prüffrage | Geeigneter Befund |
|---|---|
| Welche Arbeit kommt an? | Angeforderte Auftragslisten, Speicherungen und Berichte je Minute, soweit protokolliert |
| Welche Arbeit wird fertig? | Erfolgreich abgeschlossene Vorgänge je Minute; Fehler und Timeouts gesondert |
| Wie lange warten die Benutzer? | Antwortzeiten derselben Aufgaben, einschließlich auffällig langsamer Einzelaufrufe |
| Was arbeitet gleichzeitig? | Zum Beispiel Berichte, Import, Wartungsjob oder andere Anwendungen |
Die Anzahl angemeldeter Benutzer beschreibt die tatsächliche Last nur unzureichend. Zehn Benutzer können viele Abfragen auslösen; hundert angemeldete Benutzer können gerade nichts tun.
Beispielbefund: In der Spitzenzeit kommen mehr Speicheraufträge an, während die Anzahl erfolgreicher Abschlüsse kaum steigt. Gleichzeitig wachsen Antwortzeiten und die Warteschlange der Anwendung. Das spricht für einen Rückstau. Welche Ressource oder welcher Konflikt ihn verursacht, müssen die nächsten Schritte zeigen.
Prüfen Sie auch den Arbeitsmix: Eine Minute mit vielen kurzen Suchabfragen ist ein anderer Vergleichsfall als eine Minute mit mehreren großen Berichten.
Schritt 2: Hohe CPU-Last richtig einordnen
Sehen Sie zuerst im vorhandenen Monitoring des Betriebssystems oder auf einem Windows-Server im Task-Manager nach: Steigt die CPU-Auslastung des Prozesses sqlservr.exe im betroffenen Zeitraum? Oder beansprucht ein anderer Prozess den Rechner?
Betrachten Sie den Verlauf über das Zeitfenster. Ein kurzer Ausschlag erklärt keine minutenlange Störung. Die mittlere Auslastung des gesamten Rechners kann außerdem verdecken, dass einzelne logische Prozessoren stark beschäftigt sind. Bei virtuellen Maschinen gehören die zugeteilten und tatsächlich verfügbaren CPU-Ressourcen zum Befund. Diesen Einstieg beschreibt auch die Microsoft-Anleitung zu hoher CPU-Last.
Halten Sie drei Größen auseinander:
| Messgröße | Bedeutung |
|---|---|
| Antwortzeit | Zeit vom Start bis zum Ende des gemessenen Vorgangs; Messstelle dazuschreiben |
| CPU-Zeit | Rechenarbeit, die SQL Server für eine Abfrage verbraucht; bei paralleler Ausführung über alle beteiligten Worker aufsummiert |
| CPU-Auslastung | Anteil der verfügbaren CPU-Kapazität, der innerhalb eines Zeitraums belegt ist |
Eine lange Antwortzeit beweist deshalb keinen CPU-Engpass. Und eine schnellere Abfrage verbraucht nicht automatisch weniger CPU.
Ob bei echter CPU-Last mehr Kerne helfen oder eine bessere Abfrage, zeigt unser Beitrag Mehr Kerne, schnellere Kerne oder eine bessere Abfrage? mit Labormessungen.
Schritt 3: Mehr Aufrufe von teureren Aufrufen unterscheiden
Wenn Query Store den Zeitraum erfasst hat, öffnen Sie in SQL Server Management Studio unter der betroffenen Datenbank die Query-Store-Berichte. Beginnen Sie mit Top Resource Consuming Queries, wählen Sie CPU-Zeit und stellen Sie das passende Zeitfenster ein. Prüfen Sie, ob die Ansicht Gesamtverbrauch oder Durchschnitt je Ausführung zeigt. Dieselbe Auswertung liefert unsere Abfrage „Teuerste Abfragen im Zeitfenster“; führen Sie sie für beide Zeitfenster aus und legen Sie die Ergebnisse nebeneinander. Die Microsoft-Übersicht zu Query Store erläutert die Berichte.
Vergleichen Sie bei auffälligen Abfragen Aufrufzahl, CPU-Zeit je Ausführung, Laufzeit und Plan. Bei unterschiedlichen Parametern oder Ergebnismengen vergleichen Sie möglichst gleichartige Fälle. SQL-Statements und vollständige Anwendungsvorgänge sind dabei verschiedene Zähleinheiten.
- Mehr Aufrufe bei ähnlichem Aufwand je Aufruf: Die vorhandene Arbeit wird häufiger angefordert. Prüfen Sie Lastspitzen, zusätzliche Berichte, Wiederholungen oder vermehrte Anwendungsaufrufe.
- Ähnliche Aufrufzahl bei höherem Aufwand je Aufruf: Prüfen Sie Datenmenge, Parameter und Ausführungsplan. Hier führt der Diagnoseweg „SQL Server ist mal schnell und mal langsam“ weiter.
- Ähnliche CPU-Zeit je Aufruf bei längerer Laufzeit: Untersuchen Sie zusätzlich Wartezeiten und wie schnell die Anwendung die Ergebnisse abholt. Die CPU-Zahl allein erklärt die Verzögerung nicht.
Fehlt die passende Historie, halten Sie die Lücke fest und nutzen vorhandene Anwendungs- oder Monitoringdaten für den nächsten Vergleich.
CPU-Lab: Schneller fertig, mehr Rechenarbeit
In einem eigenen Lab haben wir eine rechenintensive Aggregationsabfrage über 300.000 Zeilen verglichen. Sie liefert eine Ergebniszeile und lief einmal seriell und einmal parallel mit Parallelitätsgrad vier (DOP 4).
Die Dauer sank um rund 69 Prozent, die CPU-Arbeit stieg um rund 19 Prozent. Vier Worker rechnen gleichzeitig: Die Abfrage ist früher fertig, obwohl zusammen mehr Rechenzeit anfällt. Ob das unter vielen gleichzeitigen Aufrufen noch hilft, zeigt erst ein Lastvergleich wie unten.
Im selben Lab blieb eine Abfrage, die 300.000 Zeilen an den Client lieferte, trotz MAXDOP 4 seriell. Ihre Clientdauer lag bei etwa 2,18 Sekunden, ihre CPU-Zeit in SQL Server bei etwa 0,20 Sekunden. Den größten Teil der Zeit verbrachte also nicht SQL Server mit Rechnen, sondern der Weg der Ergebnisse zum Client und ihre Verarbeitung dort. In den Wait-Statistiken zeigt sich so etwas typischerweise als ASYNC_NETWORK_IO (siehe Schritt 4).
MAXDOP begrenzt den zulässigen Parallelitätsgrad; die Einstellung erzwingt keinen parallelen Ausführungsplan. Prüfen Sie deshalb den tatsächlich verwendeten Plan. Siehe die Microsoft-Dokumentation zu MAXDOP.
Schritt 4: Wartezeiten im betroffenen Zeitfenster untersuchen
Wait Statistics zeigen, worauf die Worker von SQL Server gewartet haben. Ein Worker ist ein ausführender Arbeitsfaden. Warten gehört zum normalen Betrieb; entscheidend ist, welches Warten mit der beobachteten Verzögerung zusammenpasst.
sys.dm_os_wait_stats zählt alle abgeschlossenen Wartevorgänge seit dem Start der Instanz. Für ein Zeitfenster brauchen Sie deshalb zwei Messstände und deren Differenz. Die Zähler müssen Sie dafür nicht zurücksetzen. Zwei Dinge verfälschen den ersten Blick:
- Harmloses Hintergrundwarten. Viele Systemaufgaben warten die meiste Zeit auf Arbeit, etwa
SLEEP_TASK,LAZYWRITER_SLEEP,XE_TIMER_EVENToderBROKER_…. Ungefiltert stehen sie ganz oben, obwohl sie nichts mit Ihrem Problem zu tun haben. - Signal-Wartezeit.
signal_wait_time_msist der Teil, in dem ein Worker eigentlich weiterarbeiten könnte, aber auf einen freien CPU-Kern wartet. Ein hoher Anteil allein beweist noch keinen CPU-Druck: Bei reiner Rechenarbeit besteht fast jede Wartezeit aus Signal-Wartezeit, in unserem Labor schon bei 26 Prozent CPU-Auslastung. Aussagekräftig ist die Signal-Wartezeit je Sekunde im Verhältnis zur Zahl der Kerne, zusammen mit der CPU-Auslastung und der Warteschlange je Scheduler (runnable_tasks_count).
Ein Neustart setzt diese Zähler auf null, ebenso die Statistiken im Plan Cache. Wenn Sie wegen der Last über einen Neustart nachdenken, lesen Sie vorher Warum hilft ein Neustart, und warum nur kurz? und sichern Sie das Lagebild.
Die folgende Abfrage misst ein Fenster, filtert das Hintergrundwarten und zeigt beide Werte. Starten Sie sie, während das Problem auftritt:
/* PSG Stack · SQL Server Performance Ratgeber · Abfrage 3
Wartezeiten in einem Zeitfenster: Differenz zweier Messstände.
- Nur lesend. Setzt keine Zähler zurück.
- Läuft mit MAXDOP 1, damit die Diagnose den Server nicht zusätzlich
mit paralleler Arbeit belastet.
- Das Fenster läuft per WAITFOR; die Abfrage ist so lange beschäftigt.
Starten Sie sie, während das Problem auftritt.
- Rechte: VIEW SERVER STATE
(ab SQL Server 2022 genügt VIEW SERVER PERFORMANCE STATE).
- Ab SQL Server 2016. Geprüft im PSG-Lab auf 2017, 2019, 2022 und 2025.
- Harmloses Hintergrundwarten ist ausgefiltert. Die Liste ist nicht
vollständig; prüfen Sie unbekannte Wait-Typen in der Dokumentation.
- Wartezeiten vieler Sitzungen überlappen sich. Die Summe kann größer
sein als die Länge des Fensters.
*/
DECLARE @fenster char(8) = '00:05:00'; -- Länge des Messfensters (hh:mm:ss)
IF OBJECT_ID('tempdb..#vorher') IS NOT NULL DROP TABLE #vorher;
SELECT wait_type, waiting_tasks_count, wait_time_ms, signal_wait_time_ms
INTO #vorher
FROM sys.dm_os_wait_stats
OPTION (MAXDOP 1);
WAITFOR DELAY @fenster;
WITH differenz AS (
SELECT n.wait_type,
n.waiting_tasks_count - v.waiting_tasks_count AS wartevorgaenge,
n.wait_time_ms - v.wait_time_ms AS wartezeit_ms,
n.signal_wait_time_ms - v.signal_wait_time_ms AS signal_ms
FROM sys.dm_os_wait_stats AS n
JOIN #vorher AS v ON v.wait_type = n.wait_type
WHERE n.wait_time_ms - v.wait_time_ms > 0
AND n.wait_type NOT LIKE N'SLEEP[_]%'
AND n.wait_type NOT LIKE N'BROKER[_]%'
AND n.wait_type NOT LIKE N'XE[_]%'
AND n.wait_type NOT LIKE N'QDS[_]%'
AND n.wait_type NOT LIKE N'HADR[_]%'
AND n.wait_type NOT LIKE N'PARALLEL[_]REDO[_]%'
AND n.wait_type NOT IN (
N'AZURE_IMDS_VERSIONS', N'CHECKPOINT_QUEUE', N'CHKPT', N'CLR_AUTO_EVENT', N'CLR_MANUAL_EVENT',
N'CLR_SEMAPHORE', N'DBMIRROR_DBM_EVENT', N'DBMIRROR_EVENTS_QUEUE',
N'DBMIRROR_WORKER_QUEUE', N'DBMIRRORING_CMD', N'DIRTY_PAGE_POLL',
N'DISPATCHER_QUEUE_SEMAPHORE', N'EXECSYNC', N'FSAGENT',
N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX', N'KSOURCE_WAKEUP',
N'LAZYWRITER_SLEEP', N'LOGMGR_QUEUE', N'MEMORY_ALLOCATION_EXT',
N'ONDEMAND_TASK_QUEUE', N'PREEMPTIVE_OS_FLUSHFILEBUFFERS',
N'PREEMPTIVE_XE_GETTARGETSTATE', N'PVS_PREALLOCATE',
N'PWAIT_ALL_COMPONENTS_INITIALIZED', N'PWAIT_DIRECTLOGCONSUMER_GETNEXT',
N'PWAIT_EXTENSIBILITY_CLEANUP_TASK', N'REDO_THREAD_PENDING_WORK',
N'REQUEST_FOR_DEADLOCK_SEARCH', N'RESERVED_MEMORY_ALLOCATION_EXT', N'RESOURCE_QUEUE', N'SERVER_IDLE_CHECK',
N'SNI_HTTP_ACCEPT', N'SOS_WORK_DISPATCHER', N'SP_SERVER_DIAGNOSTICS_SLEEP',
N'SQLTRACE_BUFFER_FLUSH', N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
N'SQLTRACE_WAIT_ENTRIES', N'VDI_CLIENT_OTHER', N'WAIT_FOR_RESULTS',
N'WAITFOR', N'WAITFOR_TASKSHUTDOWN', N'WAIT_XTP_CKPT_CLOSE',
N'WAIT_XTP_HOST_WAIT', N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG', N'WAIT_XTP_RECOVERY')
)
SELECT TOP (15)
wait_type,
wartevorgaenge,
CAST(wartezeit_ms / 1000.0 AS decimal(18,1)) AS wartezeit_s,
CAST(signal_ms / 1000.0 AS decimal(18,1)) AS davon_auf_cpu_s, -- bereit, aber kein freier Kern
CAST(100.0 * wartezeit_ms / NULLIF(SUM(wartezeit_ms) OVER (), 0)
AS decimal(5,1)) AS anteil_prozent,
CAST(1.0 * wartezeit_ms / NULLIF(wartevorgaenge, 0)
AS decimal(18,1)) AS ms_je_vorgang
FROM differenz
ORDER BY wartezeit_ms DESC
OPTION (MAXDOP 1);Beispielausgabe aus unserem Lab (SQL Server 2022, Fenster 25 Sekunden, gekürzt). Während des Fensters liefen 20.000 einzelne Inserts und eine Blockade von etwa zehn Sekunden:
wait_type wartevorgaenge wartezeit_s davon_auf_cpu_s anteil_prozent ms_je_vorgang
LCK_M_X 1 9.9 .0 81.8 9887.0
WRITELOG 3206 2.2 .3 18.1 .7LCK_M_X ist ein einziger langer Wartevorgang: die Blockade. WRITELOG sind viele kurze Wartevorgänge, weil jeder einzelne Insert auf das Schreiben des Transaktionsprotokolls wartet. Auf einem ruhigen Server stehen oft nur Einträge mit 0,0 Sekunden oben, etwa PREEMPTIVE_OS_…; die können Sie dann ignorieren.
Die Microsoft-Dokumentation zu Wait Statistics erklärt die einzelnen Wait-Typen. Für eine einzelne Sitzung gibt es sys.dm_exec_session_wait_stats.
Ab SQL Server 2017 erfasst Query Store die Wartezeiten zusätzlich je Abfrage. Der Bericht Query Wait Statistics hilft dann, die betroffenen Abfragen zu einer Wartekategorie zu finden. Dort sind mehrere Wait-Typen zu Kategorien zusammengefasst. Die Kategorie CPU bedeutet Scheduler-Warten, also „bereit, aber kein freier Kern“; die gemessene Rechenzeit prüfen Sie gesondert. Die Microsoft-Zuordnung der Wait-Typen erklärt diese Kategorien.
Nutzen Sie auffällige Werte als Wegweiser:
| Beobachtung im passenden Zeitraum | Nächste Prüfung |
|---|---|
Lock-Waits, etwa LCK_M_X | Wer blockiert wen? Dem Diagnoseweg zu Blocking und Timeouts folgen |
SOS_SCHEDULER_YIELD und hoher Signal-Anteil, zusammen mit hoher CPU-Auslastung | CPU-intensive Abfragen, Aufwand je Aufruf und gleichzeitige Arbeit vergleichen (Schritt 3) |
Datenlese-Waits, etwa PAGEIOLATCH_SH | Physische Lesezugriffe und Latenz je Datei untersuchen, etwa mit sys.dm_io_virtual_file_stats |
Warten auf Ausführungsspeicher, etwa RESOURCE_SEMAPHORE | Speicherzusagen (Memory Grants) großer Abfragen prüfen, etwa mit sys.dm_exec_query_memory_grants |
ASYNC_NETWORK_IO | SQL Server wartet, bis der Client die Ergebnisse abholt. Meist große Ergebnismengen oder zeilenweise Verarbeitung in der Anwendung, seltener das Netzwerk selbst |
Parallelitäts-Waits, etwa CXPACKET oder CXCONSUMER | Den beteiligten Plan und die Verteilung der Arbeit untersuchen; Laufzeit und CPU-Arbeit danebenlegen. CXCONSUMER gilt seit SQL Server 2016 SP2 und 2017 CU3 meist als unkritisch |
Ein hoher Eintrag in einer Wait-Liste bestimmt noch keine Konfigurationsänderung. Besonders Parallelitäts-Waits brauchen den Zusammenhang der konkreten Ausführung.
Waits-Lab: 24 Sekunden Warten in drei Sekunden Echtzeit
In einem eigenen Versuch warteten acht getrennte Sitzungen gleichzeitig jeweils drei Sekunden mit WAITFOR.
Die acht Wartezeiten überlappen sich. Zusammen ergeben sie rund 24 Sekunden, obwohl auf der Uhr nur rund drei Sekunden vergehen. Der Versuch erzeugt absichtlich Warten und belegt keinen Engpass.
Dasselbe gilt beim Lesen von Wait-Statistiken: Wartezeiten vieler Sitzungen oder paralleler Worker überlagern sich, die Summe kann größer sein als die verstrichene Zeit. Addieren Sie CPU-Zeit und aufsummierte Wartezeiten nicht zu einer vermeintlichen Antwortzeit.
Wait-Summen-Lab: Mehr Wartezeit, trotzdem schneller
Was das für die Bewertung einer Änderung bedeutet, zeigt der Aggregationsbericht aus unserem gemischten Last-Lab (siehe Schritt 5). Query Store hat für jede Einstellung 87 Ausführungen des Berichts erfasst: Laufzeit, CPU-Zeit und Wartezeit, jeweils gemittelt je Ausführung.
| Einstellung | Laufzeit | CPU-Zeit | Summe der Wartezeiten |
|---|---|---|---|
| Seriell (MAXDOP 1) | 2,14 s | 1,96 s | 0,19 s |
| Parallel, MAXDOP 4 | 0,84 s | 2,62 s | 11,96 s |
| Parallel, MAXDOP 8 | 0,48 s | 2,62 s | 13,24 s |
Mit MAXDOP 8 war der Bericht rund 78 Prozent schneller als seriell, obwohl seine aufsummierte Wartezeit von 0,19 auf 13,24 Sekunden stieg. Fast alles davon ordnet Query Store der Kategorie Parallelism zu (12,92 Sekunden): Die parallelen Worker warten gleichzeitig aufeinander, und jede dieser Wartezeiten wird mitgezählt. Wer nur die Wait-Summe betrachtet, hätte beide parallelen Einstellungen für schlechter gehalten als die serielle, obwohl sie deutlich schneller waren. Und von MAXDOP 4 auf 8 stieg die Summe weiter, während die Laufzeit weiter sank. Diese Werte je Abfrage zeigt in SQL Server Management Studio der Query-Store-Bericht Query Wait Statistics (ab SQL Server 2017).
Waits erklären, wie eine Ausführung abläuft. Ob eine Änderung hilft, zeigen die Laufzeit der betroffenen Aufgabe und die übrige Arbeitslast unter realer Last. Die übrige Arbeitslast betrachtet Schritt 5 mit Clientmessungen aus demselben Lab: Dort wurden die kurzen Anwendungsvorgänge mit MAXDOP 8 langsamer; die genaue Ursache dafür hat der Versuch nicht isoliert.
Schritt 5: Änderungen mit der übrigen Arbeitslast prüfen
Formulieren Sie vor einer Änderung die erwartete Wirkung: etwa weniger CPU-Arbeit für dieselbe Suche oder kürzere Wartezeiten der Speicheraufträge. Vergleichen Sie anschließend unter ähnlicher Last und mit demselben Arbeitsmix.
Prüfen Sie neben der optimierten Abfrage auch erfolgreich abgeschlossene Vorgänge, Fehler, Timeouts und die Antwortzeiten anderer Aufgaben. Eine Änderung kann einem Bericht helfen und zugleich die kurzen Anwendungsvorgänge verzögern.
Gemischtes Last-Lab: Schnellere Berichte, langsamere Anwendungsvorgänge
In einem weiteren eigenen Lab haben wir eine feste Last vorgegeben: 800 kurze Anwendungsvorgänge pro Sekunde und zusätzlich zwei Berichtsarten, zusammen ein Bericht pro Sekunde. Die eine Berichtsart aggregiert über vier Tabellen und rechnet viel, die andere sortiert. Zwei von zehn gemessenen Einstellungen zeigen die Abwägung:
p99 ist die Schwelle, unter der 99 Prozent der gemessenen Einzelaufrufe lagen; p95 entsprechend 95 Prozent. Für die Berichte verwenden wir p95, weil es von ihnen deutlich weniger Messwerte gibt als von den kurzen Vorgängen. Die Werte stammen aus den einzelnen Clientmessungen, nicht aus Query-Store-Mittelwerten. Der Kostenschwellwert (Cost Threshold for Parallelism) ist in beiden Zeilen gleich; die Messreihe hat ihn in anderen Einstellungen verändert.
Mit MAXDOP 8 waren beide Berichtsarten schneller, die langsamsten kurzen Vorgänge dagegen langsamer. Der Unterschied war wiederholbar: In den einzelnen Läufen lag p99 der kurzen Vorgänge bei MAXDOP 4 zwischen etwa 25 und 32 ms, bei MAXDOP 8 zwischen etwa 46 und 59 ms.
Bemerkenswert ist, was nicht passierte: Die CPU-Auslastung von SQL Server lag in beiden Einstellungen nur bei rund 35 Prozent der acht CPUs und stieg mit MAXDOP 8 nicht an. Ein CPU-Engpass erklärt den Anstieg also nicht; woran die kurzen Vorgänge genau warteten, hat der Versuch nicht isoliert. Außerdem hielten alle zehn Einstellungen die vorab gesetzten Ziele ein (p99 der kurzen Vorgänge höchstens 100 ms, p95 der Berichte höchstens 5 Sekunden). Welche Abwägung richtig ist, hängt deshalb von den Anforderungen an beide Aufgaben ab, nicht von einem allgemein besten Wert.
Ergebnis festhalten: Welche Erklärung trägt der Befund?
Ein hilfreicher Zwischenstand verbindet Beobachtung, Beleg und nächste Gegenprobe. Für das gemischte Lab könnte er so lauten:
Bei gleicher vorgegebener Last sank mit MAXDOP 8 die p95-Antwortzeit des Aggregationsberichts von 858 auf 510 ms. Gleichzeitig stieg die p99-Antwortzeit der kurzen Anwendungsvorgänge von 30 auf 53 ms, obwohl die CPU-Auslastung nicht stieg. Als Nächstes prüfen wir, welche Einstellung die vereinbarten Antwortzeitziele beider Aufgaben unter dem erwarteten Arbeitsmix erfüllt, und untersuchen die Wartezeiten der kurzen Vorgänge.
Für Ihren eigenen SQL Server ergänzen Sie Zeitraum, Lastmenge, betroffene Abfragen und Messquelle. Wenn mehr Arbeit ankommt, prüfen Sie Kapazität und Gleichzeitigkeit. Wenn einzelne Aufrufe teurer werden, untersuchen Sie deren Pläne und Datenzugriffe. Wenn Vorgänge vor allem warten, verfolgen Sie die passende Ressource oder Blocking-Kette. So führt der Befund zu einer überprüfbaren nächsten Maßnahme.