Diagnose-Checkliste: – SQL Server Performance

von

Diagnose-Checkliste:

Mein SQL Server ist langsam — was jetzt?

Diese Checkliste ist kein Ersatz für die Analyse-Methodik aus Kapitel 31 — sie ist der Schnellstart, wenn das Telefon klingelt und der Controller schon wartet. Vier Schritte, zeitlich geordnet: Von der sofortigen Lageeinschätzung (5 Minuten) bis zur erweiterten Diagnose, wenn der erste Scan einen Verdacht erhärtet hat. Am Ende: Notfall-Maßnahmen für den Fall, dass Analyse und Lösung nicht zusammen auf einmal möglich sind.

Wichtig: Diese Checkliste setzt voraus, dass du Zugriff auf die Instanz hast. Wenn der Server komplett überlastet ist und keine Verbindung mehr annimmt, ist der erste Schritt die DAC-Verbindung (Dedicated Admin Connection) — entweder lokal über sqlcmd -A oder remote, wenn remote admin connections auf 1 steht (Anhang C).

Schritt 1 — Sofort-Check: Was sagt der Server gerade? (5 Minuten)

Bevor du irgendetwas änderst, willst du wissen: Was wartet der Server gerade? Die Wait Statistics geben dir die Antwort — und innerhalb von 60 Sekunden weißt du, in welche Richtung die Analyse geht.

-- Top-Wait-Types seit letztem SQL Server-Neustart
-- Signal Wait = CPU-Hunger, Resource Wait = externe Ressource
SELECT TOP 10
    wait_type,
    waiting_tasks_count,
    wait_time_ms / 1000.0 AS wait_time_sek,
    signal_wait_time_ms * 100.0 / NULLIF(wait_time_ms, 0) AS signal_wait_pct
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
    'SLEEP_TASK', 'WAITFOR', 'BROKER_TO_FLUSH', 'BROKER_TASK_STOP',
    'CLR_AUTO_EVENT', 'DISPATCHER_QUEUE_SEMAPHORE', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
    'HADR_WORK_QUEUE', 'ONDEMAND_TASK_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH',
    'RESOURCE_QUEUE', 'SERVER_IDLE_CHECK', 'SLEEP_DBSTARTUP',
    'SLEEP_DCOMSTARTUP', 'SLEEP_MASTERDBREADY', 'SLEEP_MASTERMDREADY',
    'SLEEP_MASTERUPGRADED', 'SLEEP_MSDBSTARTUP', 'SLEEP_TEMPDBSTARTUP',
    'SNI_HTTP_ACCEPT', 'SP_SERVER_DIAGNOSTICS_SLEEP', 'SQLTRACE_BUFFER_FLUSH',
    'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', 'WAIT_XTP_OFFLINE_CKPT_NEW_LOG')
ORDER BY wait_time_ms DESC;

Was du im Ergebnis siehst — und was es bedeutet:

  • CPU > 80%? Und Signal Wait-Anteil > 25%? → Scheduler-Überlastung. Weiter mit Kapitel 9 und 15.
  • PAGEIOLATCH_SH / PAGEIOLATCH_EX dominant? → IO-Problem. Weiter mit Kapitel 10.
  • LCK_M_* dominant? → Blocking oder Deadlocks. Weiter mit Kapitel 14.
  • PAGELATCH_UP auf Seiten 2:1:1, 2:1:2 oder 2:1:3? → TempDB-Contention. Weiter mit Kapitel 13.
  • PLE unter 300 × (RAM_GB / 4)? → Buffer Pool Druck. Weiter mit Kapitel 11.
  • RESOURCE_SEMAPHORE dominant? → Memory Grant-Engpass. Abfragen warten auf Arbeitsspeicher. Weiter mit Kapitel 12.
  • SOS_SCHEDULER_YIELD, THREADPOOL, CXPACKET hoch? → CPU-Sättigung oder Parallelismus-Probleme. Kapitel 9 und 15.
  • Schritt 2 — Konfiguration prüfen: Die häufigsten Fehlkonfigurationen (10 Minuten)

    Viele Performance-Probleme sind keine Abfrageprobleme — sie sind Konfigurationsprobleme, die sich als Performance-Probleme verkleiden. Dieser Check dauert 10 Minuten und schließt die häufigsten Kandidaten aus.

  • max server memory korrekt gesetzt? Wert 2147483647 (Standardwert) auf einem Server mit weniger als 2 TB RAM bedeutet: nie angepasst worden.
  • MAXDOP sinnvoll konfiguriert? Wert 0 auf einem NUMA-System mit vielen Cores ist ein Warnsignal.
  • cost threshold for parallelism > 5? Standardwert 5 führt zu Parallelismus auch bei trivialen Abfragen — CPU-Verschwendung.
  • priority boost = 0? Wenn nicht: sofort korrigieren, bevor du weiter analysierst.
  • TempDB: Gleich viele Datenbankdateien wie logische CPUs (maximal 8)? Zu wenige Dateien = PAGELATCH-Contention.
  • Kompatibilitätslevel aktuell (≥ 140 für SQL 2017+)? Level 110 oder 120 auf modernem SQL Server bedeutet: alter Cardinality Estimator aktiv.
  • Instant File Initialization aktiviert? Ohne IFI dauert jedes Datenbankdatei-Wachstum so lange wie das Nullschreiben der Bytes — bei 10 GB Autogrowth sind das Minuten.
  • Schritt 3 — Top-Queries identifizieren (15 Minuten)

    Wenn Konfiguration passt und Wait Statistics einen Abfrageverdacht ergeben: Top-Abfragen nach CPU und nach IO isolieren. Das sind die Kandidaten für die eigentliche Analyse.

  • sys.dm_exec_query_stats: Top 10 nach total_worker_time (CPU) und Top 10 nach total_logical_reads (IO) ausgeben.
  • Für jede verdächtige Abfrage: Tatsächlichen Ausführungsplan holen (SET STATISTICS XML ON oder Live Query Statistics in SSMS).
  • Warnungen im Plan vorhanden? Gelbe Ausrufezeichen bedeuten: fehlende Statistiken, Spill auf Festplatte, Implicit Conversion. Jeder einzelne davon kann die Abfrage um Faktor 10–100 verlangsamen.
  • Missing Index Hints im Plan? SQL Server schlägt sie nicht immer richtig vor — aber ein Hinweis ist ein Hinweis.
  • Estimated Rows ≈ Actual Rows? Große Abweichungen (Faktor > 10) = Statistikproblem. Kapitel 16.
  • Nested Loops bei großen Datenmengen? Fast immer ein Kardinalitätsschätzfehler. Kapitel 15.
  • CONVERT_IMPLICIT im Plan? Implicit Conversion verhindert Index-Nutzung. Kapitel 21 (SARGability).
  • Schritt 4 — Erweiterte Diagnose nach Fund (je nach Befund aus Schritt 1–3)

     

    Befund

    Nächster Schritt

    Kapitel

    CPU dominant (Signal Wait > 25%)

    Compilation Rate prüfen (Compilations/sec > 100/sec ist ein Warnsignal), Plan Cache analysieren

    9, 16, 18

    IO dominant (PAGEIOLATCH)

    sys.dm_io_virtual_file_stats: Latenzen pro Datei. Autogrowth-Events im Default Trace prüfen.

    10

    Memory-Druck (PLE niedrig)

    sys.dm_os_memory_clerks: Wer verbraucht Speicher? sys.dm_os_buffer_descriptors: Welche DB füllt den Buffer Pool?

    11

    Blocking (LCK_M_*)

    sys.dm_exec_requests + sys.dm_exec_sessions: Blocking-Chain aufbauen. Deadlock-Graph aus System Health Session lesen.

    14

    TempDB-Contention (PAGELATCH)

    Anzahl TempDB-Dateien prüfen, Version Store prüfen, temporäre Objekte in Top-Abfragen identifizieren.

    13, 29

    Verdacht Parameter Sniffing

    sys.dm_exec_query_stats: min_elapsed_time vs. max_elapsed_time vergleichen. Faktor > 100 = klarer Verdacht.

    18

    Verdacht Plan Regression

    Query Store öffnen: "Regressed Queries"-Bericht. Planwechsel auf Zeitachse identifizieren.

    16, 19

    Tabelle D.1: Befunde und nächste Schritte

     

    Notfall-Maßnahmen: Wenn es gerade brennt und du stabilisieren musst

     

    Warnung: Triage ist keine Therapie

    Die folgenden Maßnahmen stabilisieren den Server — sie lösen das Problem nicht. Nach der Triage kommt die eigentliche Ursachenanalyse. Wer nur Symptome bekämpft, sieht dasselbe Problem eine Woche später wieder.

     

  • Blocking-Head identifizieren (sys.dm_exec_requests, blocking_session_id) und entscheiden ob KILL vertretbar ist. Risiko: laufende Transaktion wird zurückgerollt.
  • Einzelnen Plan aus dem Cache entfernen: DBCC FREEPROCCACHE (plan_handle) — nur, wenn Parameter Sniffing als Ursache sicher ist. Vollständiger FREEPROCCACHE ist der letzte Ausweg, nicht der erste.
  • Resource Governor: Wenn ein unkontrollierter Report-Job die CPU auffrisst, eine Resource Pool-Grenze (z.B. 20% MAX_CPU_PERCENT) als Sofortmaßnahme setzen.
  • Query Store Forced Plan: Wenn ein bekannter guter Plan existiert, ihn sofort forcieren — das hält bis zur nächsten manuellen Änderung.
  • Statistiken manuell aktualisieren: UPDATE STATISTICS [Tabelle] WITH FULLSCAN auf den betroffenen Tabellen — kann einen schlechten Plan sofort reparieren.
  • Für die vollständige Analyse-Methodik — von der ersten Verbindung bis zum strukturierten Abschlussbericht — siehe Kapitel 31. Die drei Fallstudien in den Kapiteln 32 bis 34 zeigen, wie diese Checkliste in der Praxis angewendet wurde.

     

    Noch Fragen? Frag Uli

    Du hast eine Frage zu diesem Thema? Schreib sie einfach hier rein. Ich antworte persönlich, kurz und ohne Verkaufsgespräch.

    Antwort innerhalb von 24 Stunden

    Deine Mailadresse nutze ich nur, um dir zu antworten. Kein Newsletter, keine Weitergabe. Zur Datenschutzerklärung