Wait Types Referenz:
Die wichtigsten Wait Types — Ursachen, Bedeutung und Kapitelverweise
Wait Statistics sind das Röntgenbild deines SQL Servers. Diese Referenz listet alle Wait Types auf, die im Buch behandelt werden — alphabetisch sortiert, mit Kategorie, typischer Ursache, Einordnung (normal vs. problematisch) und Verweis auf das ausführliche Kapitel. Wer tiefer einsteigen will, findet dort die vollständige Diagnose-Methodik mit DMV-Abfragen, Benchmarks und Gegenmaßnahmen.
Bevor du in diese Liste springst, zwei fundamentale Konzepte:
Signal Wait vs. Resource Wait
Jeder Wait hat zwei Anteile: den Resource Wait (Warten auf die eigentliche Ressource — Disk, Speicher, Sperre) und den Signal Wait (Warten darauf, dass der Thread nach Ressourcenverfügbarkeit wieder auf dem CPU-Scheduler eingeplant wird). Die Relation ist entscheidend: Wenn der Signal Wait-Anteil am Gesamt-Wait hoch ist (Faustregel: >25%), ist der CPU-Scheduler überlastet — es gibt zu wenig Kerne für die wartenden Threads. Resource Waits hingegen zeigen wo die eigentliche Ressource der Flaschenhals ist. Beide Werte liefert sys.dm_os_wait_stats: signal_wait_time_ms und (wait_time_ms – signal_wait_time_ms) = resource_wait_time_ms. (→ Kap. 9)
Baseline und Einordnung
Ein einzelner Wait Type ist ohne Kontext wertlos. CXPACKET mit 50% Anteil auf einem Reporting-Server ist normal. Auf einem OLTP-Server mit MAXDOP 0 ist es ein Problem. Deshalb gilt: Immer eine Baseline erheben (Wait Type-Verteilung unter normaler Last), und Abweichungen von der Baseline untersuchen — nicht absolute Zahlen allein bewerten. Idle Waits (SLEEP_TASK, WAITFOR, BROKER_TO_FLUSH, SQLTRACE_BUFFER_FLUSH u.a.) vor der Analyse herausfiltern, damit echte Waits sichtbar werden. (→ Kap. 9, 31)
|
Tipp: Idle Waits herausfiltern |
|---|
|
Vor der Analyse Idle Waits aus sys.dm_os_wait_stats entfernen. Diese Waits entstehen, wenn SQL Server auf Arbeit wartet und verfälschen das Bild. Die vollständige Filterliste mit Beispielabfrage findest du in Kapitel 9 und im Anhang E (DMV-Spickzettel). |
Wait Types Referenztabelle
Die Tabelle ist alphabetisch nach Wait Type sortiert. Spalte "Einordnung" bedeutet: "Normal" = tritt regelmäßig auf und ist in typischen Umgebungen kein Alarmsignal; "Warnung" = verdient Aufmerksamkeit, wenn dominant; "Kritisch" = sofortiger Handlungsbedarf.
|
Wait Type |
Kategorie |
Typische Ursache |
Einordnung |
Kap. |
|---|---|---|---|---|
|
ASYNC_NETWORK_IO |
Netzwerk |
Client liest Ergebnis nicht schnell genug ab — SQL Server wartet, dass der Client den Netzwerkpuffer leert. Häufig bei großen Result Sets oder langsamen Clients. |
Normal bei langsamen Clients; Warnung, wenn dominant |
9 |
|
BACKUPIO |
IO / Backup |
IO-Operationen während eines Backup-Vorgangs. Tritt auf während BACKUP DATABASE oder BACKUP LOG läuft. |
Normal während Backup-Fenstern |
10 |
|
CXCONSUMER |
CPU / Parallelismus |
Consumer-Thread wartet in einem parallelen Plan auf Daten vom Producer-Thread. Eng verwandt mit CXPACKET, ab SQL 2017 separat ausgewiesen. |
Normal bei parallelen Queries; Warnung, wenn Signal Wait hoch |
9, 15 |
|
CXPACKET |
CPU / Parallelismus |
Synchronisation zwischen parallelen Threads: ein Thread wartet, dass andere Thread-Zweige aufholen. Sieht dramatisch aus, ist es oft nicht. |
Normal bei parallelen Queries; Problem, wenn Signal Wait-Anteil > 25% |
9, 15 |
|
IO_COMPLETION |
IO |
Warten auf Abschluss asynchroner IO-Operationen (z.B. Restore, Datenbankoperationen außerhalb des Buffer Pools). |
Normal; Warnung, wenn p95 > 20 ms |
10 |
|
LCK_M_IS |
Locking |
Intent Shared Lock — Vorläufer-Lock für Shared Locks auf tieferer Ebene. Selten Ursache von Performance-Problemen. |
Normal |
14, 27 |
|
LCK_M_S |
Locking |
Shared Lock durch Exclusive Lock blockiert. Klassisches Read-Write-Blocking: Leser wartet auf Schreiber oder umgekehrt. |
Warnung, wenn häufig und lang |
14, 27 |
|
LCK_M_U |
Locking |
Update Lock — Übergangs-Lock zwischen Shared und Exclusive. Häufig im klassischen "Lesen, dann Schreiben"-Deadlock-Muster. |
Warnung bei Deadlock-Mustern |
14, 28 |
|
LCK_M_X |
Locking |
Exclusive Lock — eine Transaktion hält exklusiven Schreibzugriff. Andere Transaktionen warten. Zeigt Blocking oder Deadlocks an. |
Warnung, wenn häufig |
14 |
|
PAGEIOLATCH_EX |
IO / Buffer Pool |
Warten beim Schreiben einer Datenbankseite aus dem Buffer Pool auf Disk. Zeigt IO-Engpass beim Schreiben an. |
Warnung, wenn p95 > 20 ms |
10, 11 |
|
PAGEIOLATCH_SH |
IO / Buffer Pool |
Warten beim Laden einer Datenbankseite von Disk in den Buffer Pool (Lesezugriff). Der häufigste IO-Wait in speicherarmen Umgebungen. |
Warnung, wenn p95 > 20 ms; Kritisch bei > 100 ms |
10, 11 |
|
PAGEIOLATCH_UP |
IO / Buffer Pool |
Update Latch auf einer IO-Seite. Tritt bei bestimmten Allokationsoperationen auf. |
Normal in kleinen Mengen |
10, 13 |
|
PAGELATCH_EX |
Latch / TempDB |
Exklusiver Latch auf einer Datenbankseite (kein IO-Latch). Klassisches Symptom für TempDB-Allokations-Contention (PFS/GAM/SGAM-Seiten). |
Kritisch, wenn auf TempDB-Allokationsseiten |
13 |
|
PAGELATCH_SH |
Latch |
Shared Latch auf einer Datenbankseite. Zeigt Contention auf häufig gelesene Seiten an. |
Normal; Warnung, wenn dominant auf System-Seiten |
13 |
|
PAGELATCH_UP |
Latch / TempDB |
Update Latch — klassisches Symptom für TempDB PFS/GAM/SGAM-Contention bei vielen gleichzeitigen Temp-Tabellen-Allokationen. |
Warnung, wenn auf TempDB 2:1:1, 2:1:2, 2:1:3-Seiten |
13 |
|
PREEMPTIVE_OS_* |
OS-Calls |
SQL Server ruft Windows-API auf und wartet auf Rückkehr (präemptiv, d.h. außerhalb von SQLOS-Kontrolle). Dutzende Varianten — z.B. PREEMPTIVE_OS_FILEOPS, PREEMPTIVE_OS_QUERYREGISTRY. |
Normal in kleinen Mengen; Warnung, wenn > 5% der Gesamtwaits |
9 |
|
RESOURCE_SEMAPHORE |
Memory / Grants |
Abfrage wartet auf Memory Grant für Sort oder Hash Join. Zeigt Memory Grant-Engpass an: zu viele gleichzeitige Abfragen mit hohem Speicherbedarf, oder Schätzungen zu groß. |
Warnung, wenn häufig — zeigt Speicherdruck oder falsche Schätzungen an |
12 |
|
SLEEP_TASK |
Intern / Idle |
Thread schläft und wartet auf Arbeit (Idle Wait). Erscheint in der Top-Liste von Wait Statistics, hat aber keinen Performance-Einfluss. |
Normal — herausfiltern vor Analyse |
9 |
|
SOS_SCHEDULER_YIELD |
CPU |
Thread gibt CPU freiwillig ab, weil er zu lange gelaufen ist (SQLOS-Kooperation). Hohe SOS_SCHEDULER_YIELD-Werte zeigen CPU-intensive Workloads oder CPU-Sättigung. |
Warnung, wenn dominant — zeigt CPU-Hunger an |
9, 15 |
|
SQLTRACE_BUFFER_FLUSH |
Intern / Trace |
SQL Trace (Legacy-Profiler) schreibt seinen Puffer auf Disk. Nur relevant, wenn SQL Trace aktiv ist. |
Normal, wenn SQL Trace aktiv; herausfiltern sonst |
8 |
|
THREADPOOL |
CPU / Threading |
Kein Worker Thread verfügbar — alle max_worker_threads-Threads sind beschäftigt. Neue Anfragen können nicht bearbeitet werden. Extremes CPU/Threading-Problem. |
Kritisch — sofortiger Handlungsbedarf |
5, 9 |
|
WAIT_XTP_OFFLINE_CKPT_NEW_LOG |
In-Memory OLTP |
In-Memory OLTP Checkpoint-Prozess wartet auf neuen Log-Eintrag. Tritt auf, wenn In-Memory OLTP-Tabellen verwendet werden. |
Normal, wenn In-Memory OLTP aktiv |
11 |
|
WRITELOG |
IO / Transaction Log |
Warten auf das Schreiben des Transaction Log (bei COMMIT). Zeigt IO-Engpass auf dem Log-Volume an. Entscheidend für Commit-Latenz. |
Warnung, wenn p95 > 5 ms; Kritisch bei > 20 ms |
6, 10 |
Tabelle B-1: Wait Types Referenz (alphabetisch)
Ergänzende Hinweise zu ausgewählten Wait Types
CXPACKET — der am häufigsten falsch interpretierte Wait Type
Kein Wait Type wird so häufig falsch bewertet wie CXPACKET. Er erscheint immer, wenn Abfragen parallel ausgeführt werden — was auf jedem System mit MAXDOP > 1 und einigermaßen komplexen Abfragen der Fall ist. Das macht ihn fast überall zur Nummer 1 oder 2 in der Wait-Liste. Die entscheidende Frage ist nicht "ist CXPACKET vorhanden?" sondern "wie hoch ist der Signal Wait-Anteil?"
Niedriger Signal Wait bei CXPACKET: Parallelismus läuft sauber, Threads warten aufeinander — das ist normales Verhalten. Hoher Signal Wait bei CXPACKET: Scheduler-Überlastung, Threads können nicht eingeplant werden — das ist echte CPU-Sättigung. Die Abhilfe ist dann nicht MAXDOP senken, sondern die CPU-Last-Ursache finden. (→ Kap. 9, 15)
PAGEIOLATCH_SH — der IO-Hunger-Indikator
PAGEIOLATCH_SH ist das klassische Symptom für einen Buffer Pool, der zu klein ist. Jede PAGEIOLATCH_SH-Wait bedeutet: Diese Seite war nicht im Cache und musste von Disk geladen werden. Bei HDDs kostet das 5–15 ms, bei SSDs 0,1–0,5 ms, bei NVMe < 0,1 ms. Wenn PAGEIOLATCH_SH dominant ist, zuerst prüfen: Ist max server memory korrekt gesetzt? Gibt es Speicherdruck (PLE-Einbrüche)? Ist die IO-Hardware der Engpass? (→ Kap. 10, 11)
THREADPOOL — der Notfall-Wait
THREADPOOL bedeutet: SQL Server hat keinen Worker Thread mehr frei. Neue Verbindungsanfragen hängen. Das System reagiert nicht mehr normal. Ursachen: zu hohe Verbindungsanzahl, viele lang laufende Transaktionen, zu niedriges max_worker_threads (selten). Sofortmaßnahme: Blocking-Ketten identifizieren und unterbinden. Dann Ursache analysieren, warum so viele Threads gleichzeitig aktiv sind. (→ Kap. 5, 9)
WRITELOG — das Herzschlag-Wait des Transaction Logs
Jeder COMMIT wartet auf WRITELOG. Die Latenz von WRITELOG entspricht direkt der Commit-Latenz deiner Transaktionen. Hohe WRITELOG-Waits kommen fast immer von langsamen Log-IO: HDD statt SSD für das Log-Volume, gemeinsam genutztes Log-Volume mit konkurrierenden Workloads, oder — der Klassiker — Log und Daten auf demselben Volume. Bei Sparfuchs & Partner lagen Log und Daten auf der gleichen Spindel. Ergebnis: WRITELOG p95 > 80 ms. Auf einem dedizierten NVMe-Volume wären es < 0,5 ms. (→ Kap. 6, 10)
PAGELATCH_EX auf TempDB — Contention erkennen
PAGELATCH_EX auf den TempDB-Allokationsseiten (Datenbank-ID 2, Datei-ID 1, Seiten 1, 2, 3) ist das Erkennungszeichen für TempDB-Allokations-Contention. Diese Seiten (PFS, GAM, SGAM) werden bei jeder Temp-Tabellen-Allokation aktualisiert — unter hoher Parallelität entsteht ein Serialisierungs-Engpass. Lösung: Mehr TempDB-Datendateien (eine pro logischem Kern, max. 8) und In-Memory-Tabellenvariablen statt #temp-Tabellen wo möglich. (→ Kap. 13)
RESOURCE_SEMAPHORE — wenn Abfragen auf Speicher warten
RESOURCE_SEMAPHORE-Waits bedeuten: Abfragen stehen in der Warteschlange für Memory Grants. SQL Server hat nur einen bestimmten Anteil des verfügbaren Speichers für gleichzeitige Query Grants freigegeben. Wenn viele Abfragen gleichzeitig große Sortierungen oder Hash-Joins durchführen, entsteht Konkurrenz um diesen Speicherpool. Mögliche Ursachen: zu viele gleichzeitige Abfragen, überschätzte Memory Grants durch falsche Kardinalitätsschätzungen, oder schlicht zu wenig RAM. (→ Kap. 12)
Wait Types nach Kategorie
Wer nicht alphabetisch sucht, sondern nach Problemkategorie, findet hier eine thematische Übersicht. Die Kategorie gibt den primären Engpass an — nicht den einzigen.
|
Kategorie |
Wait Types |
Was das bedeutet |
|---|---|---|
|
CPU / Parallelismus |
CXPACKET, CXCONSUMER, SOS_SCHEDULER_YIELD, THREADPOOL |
CPU-Sättigung oder Parallelismus-Probleme. Zuerst MAXDOP und Cost Threshold prüfen. |
|
IO / Buffer Pool |
PAGEIOLATCH_SH, PAGEIOLATCH_EX, PAGEIOLATCH_UP, IO_COMPLETION |
IO-Engpass oder zu kleiner Buffer Pool. max server memory und IO-Latenz prüfen. |
|
IO / Transaction Log |
WRITELOG, BACKUPIO |
Log-IO-Engpass. Dediziertes Log-Volume auf schnellem Medium prüfen. |
|
Locking |
LCK_M_S, LCK_M_X, LCK_M_U, LCK_M_IS |
Blocking oder Deadlocks. Abfragepläne, Transaktionsgrenzen und Isolation Level prüfen. |
|
Latch / TempDB |
PAGELATCH_EX, PAGELATCH_SH, PAGELATCH_UP |
TempDB-Allokations-Contention. Anzahl TempDB-Dateien und Temp-Tabellen-Nutzung prüfen. |
|
Memory / Grants |
RESOURCE_SEMAPHORE |
Memory Grant-Engpass. Kardinalitätsschätzungen, MAXDOP und verfügbaren RAM prüfen. |
|
Netzwerk |
ASYNC_NETWORK_IO |
Client-seitiger Engpass. Result Set-Größe und Client-Verarbeitung prüfen. |
|
Intern / Idle |
SLEEP_TASK, SQLTRACE_BUFFER_FLUSH |
Idle Waits — vor der Analyse herausfiltern, kein Handlungsbedarf. |
Tabelle B-2: Wait Types nach Kategorie
Diagnose-Workflow: Was tun, wenn Wait Statistics auffällig sind?
Wait Statistics zeigen den Engpass — aber sie lösen ihn nicht. Der Diagnose-Workflow in Kapitel 9 und 31 beschreibt den vollständigen Analyseprozess. Als Kurzreferenz hier die wichtigsten Schritte:
Ein einzelner Wait Type allein ist selten die ganze Geschichte. PAGEIOLATCH_SH und RESOURCE_SEMAPHORE zusammen erzählen eine andere Geschichte als jeder für sich: Buffer Pool zu klein, Hash-Joins spillen, und ein Kreislauf entsteht. Die Kombination der Wait Types ist der eigentliche Befund. (→ Kap. 9, 31)
|
Warnung: Keine Behandlung ohne Diagnose |
|---|
|
Der häufigste Fehler: CXPACKET sehen und sofort MAXDOP auf 1 setzen. Das ist wie Kopfschmerzen durch Amputieren des Kopfes zu behandeln. Immer zuerst verstehen, warum der Wait Type dominant ist — und erst dann eine zielgerichtete Maßnahme ergreifen. |
|
Praxisbeispiel: Wait Types in der Praxis |
|---|
|
Bei Musterwerk GmbH (Kap. 32) dominierte PAGEIOLATCH_SH in Kombination mit RESOURCE_SEMAPHORE — zu kleiner Buffer Pool und zu viele parallele Abfragen mit Hash-Joins. Die Lösung: max server memory korrekt setzen und MAXDOP anpassen. |
|
Bei Sparfuchs & Partner (Kap. 33) stand WRITELOG an erster Stelle mit p95 > 80 ms, gefolgt von PAGELATCH_UP auf TempDB-Seiten. Diagnose: Alles auf einer Spindel, kein dedizierts Log-Volume, TempDB-Contention durch eine einzige Datendatei. |
|
Bei Trendforge Digital (Kap. 34) war ASYNC_NETWORK_IO überraschend prominent — das ORM lud Result Sets komplett in den Speicher, bevor die Applikation sie konsumierte. Der SQL Server wartete auf den Client, der wartete auf das ORM. |
Eine vollständige Liste aller SQL Server Wait Types (aktuell über 900) bietet die Microsoft-Dokumentation zu sys.dm_os_wait_stats. Diese Referenz beschränkt sich auf die im Buch behandelten Wait Types — das sind die 20 Wait Types, die in der Praxis 80–90% aller Performance-Probleme abdecken.
