Wissen

Praxis-Artikel und Buchkapitel zu SQL-Performance, Sicherheit und Hochverfügbarkeit – alle frei verfügbar.

Beratung

Festpreis-Analyse mit Bericht und Handlungsempfehlung – oder strategische Begleitung bei Architektur, Migration und Hochverfügbarkeit.

Fachbücher

Die fünfbändige Reihe „Ulis SQL-Bibliothek“ – Band 1 verfügbar. Leseprobe herunterladen!

Tools

UB.SimSQL: SQL-Server-Lastsimulator mit regelbasierten Konfigurationsempfehlungen. Lokal, ohne Cloud, ohne Abo.

Schulungen

Online-Workshops zu Performance, Sicherheit und Entwicklung – kompakt, hands-on, ohne MOC-Folienschlacht.

Wait Types Referenz: – SQL Server Performance

von

Dieser Artikel ist ein Kapitel aus:
SQL Server Performance & Troubleshooting
Praxisleitfaden, ca. 600 Seiten

[ Hier bei Amazon bestellen ]
[ Mehr zum Buch ]

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:

  • Schritt 1: Baseline erheben — sys.dm_os_wait_stats über 30 Minuten unter typischer Last sammeln
  • Schritt 2: Idle Waits herausfiltern (SLEEP_TASK, BROKER_*, WAITFOR, SQLTRACE_BUFFER_FLUSH u.a.)
  • Schritt 3: Top-5 Wait Types nach kumulierter Wartezeit identifizieren
  • Schritt 4: Signal Wait-Anteil berechnen — hohe Signal Waits zeigen CPU-Sättigung an
  • Schritt 5: Kategorie bestimmen (IO, CPU, Locking, Memory) und entsprechendes Kapitel aufschlagen
  • Schritt 6: Zweite Ebene: welche Abfragen, Sessions oder Objekte verursachen den Wait?
  • Schritt 7: Gegenmaßnahme testen und Wait Statistics nach Änderung neu erfassen
  • 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.