Monitoring ist nicht Diagnose: Warum SQL-Server-Alarme nur der Anfang sind

Björn Peters

29. Juni 2026

17 Minuten
Analoge Messanzeigen als Symbol dafür, dass SQL Server Monitoring Signale liefert, aber noch keine Diagnose ersetzt

Vor kurzem hatte ich wieder so einen Fall, bei dem auf den ersten Blick eigentlich alles recht eindeutig aussah, und genau solche Situationen zeigen aus meiner Sicht sehr gut, warum SQL Server Monitoring Diagnose nicht ersetzt.

Ein SQL Server war auffällig langsam, im Monitoring gab es entsprechende Alarme und natürlich standen sehr schnell die üblichen Verdächtigen im Raum. CPU, Storage, Netzwerk, vielleicht eine Query, vielleicht auch wieder irgendeine Anwendung, die plötzlich mehr macht als vorher.

Das ist im Alltag nichts Besonderes. Jeder, der länger mit SQL Servern arbeitet, kennt solche Situationen. Irgendwo wird ein Dashboard rot, jemand bekommt eine Mail aus dem Monitoring, ein Prozess läuft länger als erwartet und relativ schnell gibt es die erste Vermutung, woran es liegen könnte.

Und genau an dieser Stelle wird es aus meiner Sicht interessant.

Nicht, weil Monitoring schlecht wäre. Ganz im Gegenteil. Ohne Monitoring fehlt einem oft der erste Hinweis darauf, dass überhaupt etwas passiert. Aber ein Monitoring-Alert ist eben noch keine Diagnose. Er ist erst einmal nur ein Signal.

Das klingt banal, aber in der Praxis wird genau dieser Unterschied gerne übergangen.

Aus „CPU ist hoch“ wird dann schnell „der Server braucht mehr CPU“.
Bei „Network Waits“ steht plötzlich das Netzwerk im Verdacht.
Storage Waits führen gerne direkt zum Storage-Ticket.
Und wenn eine Query lange läuft, liegt der Gedanke an einen fehlenden Index meistens auch nicht weit weg.

Manchmal stimmt das auch. Das wäre ja schön einfach.

Aber sehr häufig ist es eben nur die erste Hypothese, und wenn man diese Hypothese zu früh als Ursache behandelt, dreht man unter Umständen an der falschen Stelle.

Monitoring ist wichtig, aber es erklärt nicht automatisch die Ursache

Ich möchte das direkt vorwegnehmen, weil mir dieser Punkt wichtig ist: Dieser Beitrag soll kein Plädoyer gegen Monitoring sein.

Ich halte gutes Monitoring für absolut notwendig. Gerade bei SQL Servern, die produktiv genutzt werden, möchte ich wissen, wann ein Problem begonnen hat, wie lange es lief, ob es regelmäßig wiederkommt, ob es mit bestimmten Jobs, Reports, Importen, Releases oder Lastspitzen zusammenhängt und ob sich ein Verhalten über die Zeit verändert.

Ohne solche Daten wird Troubleshooting schnell zu einer Mischung aus Erinnerung, Bauchgefühl und hektischem Nachstellen.

Monitoring liefert also Sichtbarkeit. Es hilft beim Eingrenzen, zeigt Muster und macht die Kommunikation einfacher, weil man nicht nur sagen muss „gefühlt war es langsam“, sondern zumindest einen Zeitraum und ein paar Messwerte hat.

Aber es beantwortet meistens nicht automatisch die Frage, warum etwas passiert.

Ein Alert sagt erst einmal:

Hier ist etwas auffällig.

Er sagt nicht automatisch:

Das ist die Ursache und diese Maßnahme löst das Problem.

Genau diese Trennung zwischen SQL Server Monitoring und SQL Server Monitoring Diagnose ist aus meiner Sicht einer der Punkte, die im Betrieb gerne unterschätzt werden.

Für mich beginnt SQL Server Monitoring Diagnose deshalb nicht beim Alarm selbst, sondern bei der Frage, welche Annahme dieser Alarm überhaupt auslöst.

SQL Server Monitoring Diagnose: vom Signal zur Hypothese

Wenn ich mir ein Performance-Thema anschaue, versuche ich gedanklich erst einmal ein paar Dinge auseinanderzuhalten. Das klingt vielleicht etwas theoretisch, hilft aber enorm, um nicht zu früh in eine Richtung zu laufen.

Für mich gibt es in so einer Analyse mehrere Stufen:

  • Signal
  • Symptom
  • Hypothese
  • Prüfung
  • Ursache
  • Entscheidung
Denkmodell vom Signal über Symptom Hypothese und Prüfung bis zur Ursache und Entscheidung
Ein Monitoring-Signal ist der Startpunkt. Die Diagnose entsteht erst durch Hypothese, Prüfung und Einordnung.

Ein Signal ist das, was auffällt. Zum Beispiel hohe CPU, ein bestimmter Wait Type, eine lange Laufzeit, ein rotes Dashboard oder eine Query Store Regression.

Das Symptom beschreibt, wie sich das Problem zeigt. Also zum Beispiel: Ein Report läuft statt zwei Minuten plötzlich zwanzig Minuten. Eine Anwendung reagiert bei bestimmten Aktionen langsam. Ein Import schafft sein Zeitfenster nicht mehr. Benutzer melden Timeouts.

Die Hypothese ist dann meine erste prüfbare Annahme. Zum Beispiel: Eine bestimmte Query erzeugt ungewöhnlich viel CPU. Oder: Ein Report liefert zu viele Daten an den Client. Oder: Ein Execution Plan hat sich geändert.

Die Prüfung ist der Teil, in dem ich bewusst versuche, diese Hypothese zu bestätigen oder zu widerlegen. Genau hier entscheidet sich, ob aus einer naheliegenden Vermutung tatsächlich eine belastbare technische Einordnung wird.

Die Ursache ist erst das, was ich nach dieser Prüfung auch technisch nachvollziehbar belegen kann. Und die Entscheidung ist dann der Schritt danach: Was ändern wir, was beobachten wir weiter und was lassen wir bewusst unverändert?

Das klingt nach Wortklauberei, ist aber im Alltag wichtig. Denn wenn ich eine Hypothese zu früh zur Ursache erkläre, suche ich ab diesem Moment oft nur noch nach Belegen für diese Annahme. Alles, was nicht passt, wird dann gerne ignoriert oder irgendwie passend gemacht.

Gerade bei SQL Server Performance ist das gefährlich, weil unterschiedliche Ursachen sehr ähnlich aussehen können.

Beispiel: Hohe CPU ist nicht automatisch ein CPU-Problem

Hohe CPU ist ein gutes Beispiel, weil der Reflex hier oft sehr schnell kommt.

Das Monitoring zeigt hohe CPU auf dem SQL Server. Vielleicht dauerhaft, vielleicht nur in Spitzen, vielleicht seit einem bestimmten Deployment oder immer zu einer bestimmten Uhrzeit.

Natürlich kann die Ursache sein, dass der Server zu klein dimensioniert ist. Das gibt es. Gerade bei konsolidierten Systemen, alten VMs oder Workloads, die über die Jahre gewachsen sind, ist das nicht unrealistisch.

Trotzdem wäre das für mich nicht der erste Schluss.

Ich würde zuerst wissen wollen, welche Arbeit diese CPU überhaupt erzeugt.

Auch das ist für mich ein typischer Teil von SQL Server Monitoring Diagnose: nicht nur den Messwert sehen, sondern verstehen, welche Arbeit dahintersteht.

Aktive Requests als erster Einstieg

Für einen ersten Blick kann man sich zum Beispiel die aktiven Requests ansehen. Nicht, weil diese Abfrage die Ursache findet, sondern weil sie helfen kann, die nächsten Fragen besser zu stellen.

SELECT
    r.session_id,
    r.status,
    r.command,
    r.wait_type,
    r.wait_time,
    r.cpu_time,
    r.total_elapsed_time,
    r.logical_reads,
    r.reads,
    r.writes,
    r.row_count,
    DB_NAME(r.database_id) AS database_name,
    s.host_name,
    s.program_name,
    s.login_name,
    t.text AS sql_text
FROM sys.dm_exec_requests AS r
JOIN sys.dm_exec_sessions AS s
    ON r.session_id = s.session_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
WHERE r.session_id <> @@SPID
ORDER BY r.cpu_time DESC;
SSMS-Screenshot mit aktiven Requests inklusive Wait Type CPU-Zeit Laufzeit logischen Reads Row Count Hostname und Programmname
Ein erster Blick auf aktive Requests liefert noch keine Diagnose, hilft aber dabei, die nächsten Fragen gezielter zu stellen.

Interessant sind hier nicht nur die reinen CPU-Werte. Ich möchte auch sehen, ob einzelne Sessions auffallen, aus welcher Anwendung sie kommen, ob viele logische Reads beteiligt sind, ob sehr viele Zeilen verarbeitet werden und ob die Last eher breit verteilt ist oder an wenigen Abfragen hängt.

Query Store als zweite Perspektive

Wenn Query Store aktiv ist, würde ich danach meistens versuchen, den betroffenen Zeitraum einzugrenzen und zu prüfen, welche Queries in diesem Zeitraum auffällig waren. Dabei sollte man aber aufpassen, weil Query Store Runtime Stats in Intervallen speichert. Wenn man Durchschnittswerte über mehrere Intervalle zusammenfasst, sollte man diese nicht einfach noch einmal ungewichtet mitteln.

Ein einfacher Einstieg könnte so aussehen:

SELECT TOP (20)
    qsq.query_id,
    qsp.plan_id,
    OBJECT_NAME(qsq.object_id) AS object_name,
    SUM(rs.count_executions) AS executions,
    SUM(rs.avg_duration * rs.count_executions) / NULLIF(SUM(rs.count_executions), 0) AS weighted_avg_duration,
    SUM(rs.avg_cpu_time * rs.count_executions) / NULLIF(SUM(rs.count_executions), 0) AS weighted_avg_cpu_time,
    SUM(rs.avg_logical_io_reads * rs.count_executions) / NULLIF(SUM(rs.count_executions), 0) AS weighted_avg_logical_reads
FROM sys.query_store_query AS qsq
JOIN sys.query_store_plan AS qsp
    ON qsq.query_id = qsp.query_id
JOIN sys.query_store_runtime_stats AS rs
    ON qsp.plan_id = rs.plan_id
GROUP BY
    qsq.query_id,
    qsp.plan_id,
    qsq.object_id
ORDER BY weighted_avg_cpu_time DESC;
Query-Store-Auswertung mit Query ID Plan ID Ausführungen gewichteter Laufzeit CPU-Zeit und logischen Reads
Query Store kann helfen, auffällige Abfragen nach CPU-Zeit, Laufzeit und logischen Reads zu finden. Die Ergebnisse sind aber Kandidaten für die weitere Prüfung, noch keine fertige Diagnose.

Auch das ist wieder keine fertige Diagnose.

Die Abfrage liefert Kandidaten. Danach muss man weiter prüfen: Passt der Zeitraum überhaupt zum gemeldeten Problem? Hat sich die Anzahl der Ausführungen verändert? Gibt es einen anderen Plan? Sind die logischen Reads gestiegen? Hat sich die Datenmenge verändert? Ist die Query fachlich erwartbar teuer oder macht SQL Server hier unnötig viel Arbeit?

Genau dieser letzte Punkt ist oft entscheidend. Hohe CPU kann bedeuten, dass die Hardware zu knapp ist. Sie kann aber auch bedeuten, dass SQL Server viel zu viel unnötige Arbeit macht.

Mehr CPU hilft dann vielleicht kurzfristig, löst aber nicht zwingend das eigentliche Problem.

Wait Stats: sehr hilfreich, aber nicht als alleinige Wahrheit

Wait Stats sind eines der Werkzeuge, die ich sehr gerne nutze, aber sie sind auch ein gutes Beispiel dafür, wie schnell man in eine falsche Richtung denken kann.

Eine einfache Abfrage sieht vielleicht so aus:

SELECT
    wait_type,
    waiting_tasks_count,
    wait_time_ms,
    signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type NOT LIKE 'SLEEP%'
  AND wait_type NOT LIKE 'BROKER%'
  AND wait_type NOT LIKE 'XE%'
ORDER BY wait_time_ms DESC;
SSMS-Screenshot einer Wait-Stats-Auswertung als Delta über einen konkreten Analysezeitraum
Wait Stats werden erst richtig hilfreich, wenn man sie im passenden Zeitraum und im Kontext der betroffenen Workload betrachtet.

Damit bekommt man eine erste Übersicht. Mehr aber auch nicht.

Diese Filterliste ist bewusst kurz gehalten und wäre für eine echte Analyse meistens nicht ausreichend. Außerdem sind instanzweite Wait Stats kumuliert. Sie laufen also seit dem letzten Reset beziehungsweise seit dem letzten Neustart der Instanz. Wenn ich ein konkretes Problem analysiere, bringt mir eine statische Top-Liste nur begrenzt etwas.

Interessanter ist meistens ein Delta über einen konkreten Zeitraum oder während eines reproduzierbaren Problems.

Also nicht nur:

Was steht oben?

Sondern eher:

Was hat sich während des Problems verändert?

Und dann kommen die eigentlichen Fragen:

Welche Workload lief zu diesem Zeitpunkt? Ist der Wait dauerhaft auffällig oder nur während eines bestimmten Prozesses? Gibt es eine Baseline? Welche Queries waren beteiligt? Passt das überhaupt zu dem, was Anwender oder Anwendung melden?

Ein Wait Type ist ein Hinweis. Kein Urteil.

Das klingt vorsichtig, aber genau diese Vorsicht spart in der Praxis oft Zeit.

Network Waits: Netzwerk sichtbar, aber nicht immer Ursache

Network Waits sind für mich ein besonders gutes Beispiel, weil sie im Alltag schnell in Richtung Infrastruktur geschoben werden.

Wenn SQL Server darauf wartet, dass Daten an den Client übertragen oder vom Client abgenommen werden, sieht das auf den ersten Blick natürlich nach Netzwerk aus. Und ja, manchmal ist das Netzwerk wirklich das Problem.

Aber eben nicht immer.

Ich habe mehr als einmal Situationen gesehen, in denen zuerst Netzwerk oder Infrastruktur im Verdacht standen, am Ende aber die eigentliche Frage war, warum überhaupt so viele Daten an den Client übertragen wurden.

Ein Report, der mehrere Millionen Zeilen zieht. Eine Anwendung, die mit SELECT * arbeitet. Eine Maske, die Daten im Client filtert, obwohl die Filterung besser in der Datenbank passieren sollte. Ein Tool, das Ergebnismengen langsam verarbeitet. All das kann dazu führen, dass SQL Server wartet.

Active Requests im Network-Wait-Kontext

Ein erster Blick könnte so aussehen:

SELECT TOP (20)
    r.session_id,
    r.status,
    r.wait_type,
    r.cpu_time,
    r.total_elapsed_time,
    r.logical_reads,
    r.reads,
    r.writes,
    r.row_count,
    s.host_name,
    s.program_name,
    t.text AS sql_text
FROM sys.dm_exec_requests AS r
JOIN sys.dm_exec_sessions AS s
    ON r.session_id = s.session_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
WHERE r.session_id <> @@SPID
  AND r.database_id > 4
ORDER BY
    r.total_elapsed_time DESC,
    r.logical_reads DESC,
    r.row_count DESC;

Ich würde an dieser Stelle nicht nur auf einen einzelnen Wert wie row_count schauen. Bei aktiven Requests hängt dieser Wert vom aktuellen Ausführungszustand ab und zeigt nicht automatisch das finale Resultset. Interessanter ist die Kombination aus Laufzeit, logischen Reads, Wait Type, Anwendungskontext und der Frage, welche Datenmenge die Abfrage verarbeitet oder an den Client zurückliefert.

Mir geht es hier also nicht um den Grenzwert, sondern um den Analyseweg.

Wenn ich eine Session mit Network Waits sehe, würde ich deshalb nicht sofort ein Netzwerk-Ticket eröffnen. Ich würde zuerst prüfen, welche Query läuft, welcher Client beteiligt ist, wie lange die Anfrage bereits läuft, wie viele logische Reads entstehen, welche Zeilenzahl aktuell sichtbar ist und ob die Anwendung die Ergebnismenge vielleicht langsam verarbeitet oder unnötig viel Arbeit auslöst.

Active-Requests-Auswertung mit ASYNC_NETWORK_IO Wait Type Laufzeit logischen Reads Row Count Anwendung und SQL-Text
Network Waits sind ein Signal, aber noch keine Ursache. Erst zusammen mit Laufzeit, logischen Reads, Row Count, Anwendung und SQL-Text entsteht eine prüfbare Hypothese.

Das Netzwerk kann trotzdem beteiligt sein. Aber die erste Frage wäre für mich nicht „warum ist das Netzwerk langsam?“, sondern „was passiert hier zwischen Query, Client, Datenmenge und Verarbeitung?“.

Das ist ein anderer Blick auf dasselbe Signal.

Query Store als Verbindung zwischen Signal und Query

Query Store ist für SQL Server Monitoring Diagnose sehr hilfreich, weil man damit ein allgemeines Monitoring-Signal mit konkreten Queries, Plänen und Zeiträumen verbinden kann.

Die Grundlagen und Voraussetzungen von Query Store sind in der Microsoft-Dokumentation zu Query Store gut beschrieben.

Das Monitoring sagt vielleicht nur:

Der SQL Server war zwischen 10:15 Uhr und 10:45 Uhr langsam.

Query Store kann dann helfen zu prüfen, welche Queries in diesem Zeitraum auffällig waren, ob sich Pläne geändert haben, ob einzelne Abfragen plötzlich deutlich länger liefen oder ob bestimmte Wait-Kategorien bei bestimmten Plänen sichtbar werden.

Aber auch Query Store ist kein magischer Diagnoseknopf.

Er liefert Daten, die man einordnen muss.

Wait-Kategorien im Query Store prüfen

Wenn Query Store Wait Stats verfügbar sind, kann man zum Beispiel prüfen, welche Wait-Kategorien bei welchen Plänen und in welchen Query-Store-Intervallen auffallen:

SELECT TOP (20)
    qsq.query_id,
    qsp.plan_id,
    ws.wait_category_desc,
    SUM(ws.total_query_wait_time_ms) AS total_wait_time_ms,
    AVG(ws.avg_query_wait_time_ms) AS avg_wait_time_ms,
    COUNT(*) AS wait_stat_rows
FROM sys.query_store_query AS qsq
JOIN sys.query_store_plan AS qsp
    ON qsq.query_id = qsp.query_id
JOIN sys.query_store_wait_stats AS ws
    ON qsp.plan_id = ws.plan_id
GROUP BY
    qsq.query_id,
    qsp.plan_id,
    ws.wait_category_desc
ORDER BY total_wait_time_ms DESC;
Query-Store-Wait-Stats mit Query ID Plan ID Wait-Kategorie und gesamter Wartezeit
Query Store Wait Stats helfen dabei, Wait-Kategorien mit konkreten Queries, Plänen und Zeitintervallen zu verbinden. Die Bewertung bleibt trotzdem Teil der Analyse.

Bei der Abfrage würde ich trotzdem nicht stehen bleiben.

Entscheidend bleibt wieder die Einordnung. Passt der Zeitraum zum gemeldeten Problem? Gehört die Query wirklich zu diesem Symptom? Vielleicht hat sich der Plan geändert, vielleicht ist die Last fachlich erklärbar oder die sichtbaren Waits sind eher Folge als Ursache. Zusätzlich würde ich prüfen, ob es einen Zusammenhang mit Release, Job, Import oder Datenwachstum gibt.

Query Store ist stark, wenn man die richtigen Fragen stellt.

Als weiteres Dashboard bringt er deutlich weniger.

Wie ich so eine Analyse grob angehen würde

Ich mag keine übertrieben langen Checklisten, weil sie in echten Umgebungen oft sowieso nicht sauber linear funktionieren. Trotzdem hilft mir ein grober roter Faden, damit man nicht sofort in Maßnahmen springt.

Zeitraum, Symptom und Workload eingrenzen

Zuerst würde ich den Zeitraum eingrenzen. Wann trat das Problem auf, seit wann, einmalig oder wiederkehrend, nach einem Deployment, während eines Jobs, während eines Reports oder vielleicht immer zu einer bestimmten Uhrzeit?

Danach würde ich versuchen, das Symptom sauber zu beschreiben. „SQL Server ist langsam“ reicht nicht. Mich interessiert, welche Anwendung betroffen ist, um welche Datenbank es geht, welche Benutzer oder Masken das Problem sehen und ob sich eine konkrete Query eingrenzen lässt. Genauso wichtig ist der Vergleich: Wie lange lief der Vorgang vorher und wie lange jetzt?

Im nächsten Schritt geht es um die Workload. Nicht jede Last ist ein Problem. Ein Monatsabschluss darf anders aussehen als ein normaler Dienstagmorgen. Ein Import darf Ressourcen nutzen, wenn er dafür ein definiertes Zeitfenster hat. Die Frage ist also nicht nur, ob Last vorhanden ist, sondern ob diese Last zu diesem Zeitpunkt und in dieser Form plausibel ist.

Hypothese formulieren und prüfen

Erst danach würde ich eine konkrete Hypothese formulieren. Zum Beispiel: Eine bestimmte Query erzeugt seit dem letzten Deployment deutlich mehr logische Reads. Oder: Ein Report liefert ein sehr großes Resultset an den Client. Oder: Eine Planänderung hat die Laufzeit einer Query erhöht.

Zu dieser Hypothese suche ich dann passende Daten. Nicht wahllos alles exportieren, was irgendwie verfügbar ist, sondern gezielt prüfen: aktive Requests, Query Store, Execution Plans, Wait Stats, Blocking, Job-Historie, Errorlog, Windows Counter, Storage-Latenzen, Applikationslogs, Deployment-Zeitpunkte.

Und mindestens genauso wichtig: Ich versuche bewusst, Gegenhypothesen zuzulassen.

Was müsste ich sehen, damit meine erste Vermutung falsch ist?

Gerade das ist im Troubleshooting unangenehm, weil man natürlich gerne schnell recht haben möchte. Aber oft spart es Zeit, die eigene erste Idee nicht zu früh zu verteidigen.

Einige dieser Gedanken passen auch zu meinen weiteren SQL-Server-Beiträgen auf SQL-aus-Hamburg, weil es dort ebenfalls immer wieder darum geht, nicht vorschnell vom Symptom auf die Ursache zu schließen.

Ein paar Fehlannahmen, die ich immer wieder sehe

Alerts, Waits und schnelle Schlüsse

Eine der häufigsten Fehlannahmen ist aus meiner Sicht, dass ein Alert bereits eine Diagnose ist. Das ist er nicht. Ein Alert ist ein Einstiegspunkt. Er zeigt, dass etwas auffällig ist, aber er erklärt noch nicht automatisch, warum es auffällig ist und welche Maßnahme sinnvoll wäre.

Ähnlich ist es mit Wait Stats. Der höchste Wait ist nicht automatisch die Ursache eines Problems. Waits brauchen immer Zeitraum, Workload und Kontext. Ohne diese Einordnung sieht man zwar, worauf SQL Server gewartet hat, aber noch nicht zwingend, warum diese Wartezeit entstanden ist oder ob sie wirklich zum gemeldeten Problem gehört.

Auch hohe CPU führt schnell zu der Annahme, dass mehr Hardware nötig ist. Manchmal stimmt das, gerade wenn ein System über Jahre gewachsen ist und die Ressourcen schlicht nicht mehr zur Last passen. Häufig muss man aber zuerst prüfen, welche Arbeit diese CPU überhaupt erzeugt. Wenn eine Query plötzlich deutlich mehr logische Reads verursacht oder ein Planwechsel viel mehr Arbeit produziert, löst zusätzliche CPU vielleicht kurzfristig das Symptom, aber nicht die Ursache.

Bei Storage-Waits ist der Reflex ähnlich. Natürlich kann Storage ein Problem sein, aber nicht jeder Storage-Wait bedeutet automatisch, dass ein Storage-Ticket die richtige nächste Maßnahme ist. Vielleicht liest eine Query schlicht viel zu viele Daten, vielleicht fehlt ein sinnvoller Zugriffspfad oder vielleicht passt die Workload gerade nicht zu dem, was fachlich eigentlich erwartet wurde.

Network Waits werden ebenfalls gerne zu schnell als Netzwerkproblem verstanden. Manchmal ist das Netzwerk beteiligt, keine Frage. Es kann aber genauso gut sein, dass eine Query viel zu viele Zeilen liefert, dass der Client langsam verarbeitet oder dass eine Anwendung Daten erst auf Client-Seite filtert. Dann ist das Netzwerk zwar sichtbar, aber nicht zwingend die eigentliche Ursache.

Tools ersetzen keine Bewertung

Und auch Query Store löst Performance-Probleme nicht automatisch. Query Store liefert sehr wertvolle Daten zu Queries, Plänen, Laufzeiten, Wait-Kategorien und Zeiträumen. Die Bewertung bleibt trotzdem Arbeit. Man muss weiterhin prüfen, ob der Zeitraum passt, ob die Query wirklich Teil des Problems ist, ob ein Planwechsel relevant war und ob die gemessene Last fachlich erklärbar ist.

Genauso wichtig ist die Trennung zwischen Health Check und Troubleshooting. Ein Health Check beantwortet nicht automatisch eine akute Frage wie „warum war die Anwendung gestern zwischen 10:15 Uhr und 10:45 Uhr langsam?“. Ein Health Check bewertet Zustand, Risiken und typische Schwachstellen. Troubleshooting untersucht ein konkretes Problem in einem konkreten Zeitraum mit konkretem Symptom.

Noch ein Hinweis zu Berechtigungen

Die gezeigten Abfragen sind bewusst als Einstieg gedacht und nicht als vollständiges Analysepaket. Je nach SQL-Server-Version und Umgebung braucht man dafür passende Berechtigungen, zum Beispiel VIEW SERVER STATE, VIEW DATABASE STATE oder entsprechende neuere, granularere Berechtigungen.

In produktiven Umgebungen sollte das sauber geregelt sein.

Und natürlich gilt wie immer: Nicht jedes Skript, das in einer Testumgebung unkritisch aussieht, sollte ungeprüft in jeder Produktionsumgebung laufen.

Was ich aus solchen Fällen mitnehme

Für mich ist der wichtigste Punkt: Monitoring ist notwendig, aber es ist nicht das Ende der Analyse.

Ohne Monitoring fehlt Sichtbarkeit. Mit Monitoring sieht man immerhin, dass etwas passiert. Aber aus Sichtbarkeit entsteht nicht automatisch Verständnis.

Der erste Verdacht ist erst einmal nur eine Hypothese, auch wenn er sehr plausibel klingt. Gerade bei SQL Server Performance kann die erste Erklärung falsch sein, weil CPU, Waits, Storage, Netzwerk, Query-Pläne und Applikationsverhalten eng zusammenhängen.

Ein einzelner Wert reicht selten. Kontext ist fast immer wichtiger als der isolierte Messwert. Zeitraum, Workload, Veränderung, Query-Kontext und fachliche Erwartung entscheiden darüber, ob ein Signal wirklich relevant ist.

SQL Server Monitoring Diagnose braucht deshalb mehr als einen roten Ausschlag im Dashboard. Sie braucht die Verbindung zwischen Signal, Zeitraum, Workload und einer prüfbaren technischen Hypothese.

Und nicht jedes System, in dem ein Problem sichtbar wird, ist auch die Ursache. Das ist aus meiner Sicht einer der häufigsten Denkfehler. Storage, Netzwerk oder CPU können betroffen sein, ohne dass man dort als Erstes optimieren sollte.

Fazit

SQL Server Monitoring ist wichtig. Ohne Monitoring fehlt im Betrieb ein wesentlicher Teil der Sichtbarkeit.

Aber Monitoring ist nicht Diagnose.

Ein Alert, ein Wait Type, eine CPU-Kurve oder ein rotes Dashboard zeigen zunächst nur, dass etwas auffällig ist. Die eigentliche Arbeit beginnt danach: Zeitraum eingrenzen, Symptom verstehen, Hypothese formulieren, passende Daten prüfen und auch bereit sein, die erste Vermutung wieder zu verwerfen.

Für mich ist das der eigentliche Kern guter SQL Server Monitoring Diagnose.

Nicht möglichst schnell irgendetwas ändern, sondern erst einmal sauber verstehen, worauf man eigentlich reagiert.

Das ist manchmal langsamer, als man es in einer akuten Situation gerne hätte. Am Ende ist es aber meistens der stabilere Weg.

AUTOR

Björn Peters

Björn arbeitet als Senior Consultant mit Schwerpunkt Microsoft Data Platform, SQL Server, PowerShell und Azure SQL. Er unterstützt Kunden bei Betrieb, Migration, Hochverfügbarkeit, Performance-Analyse und Troubleshooting.

Auf SQL aus Hamburg teilt er Erfahrungen aus realen Projekten – praxisnah, technisch und mit Blick auf stabile, nachvollziehbare Lösungen. Neben SQL Server interessiert er sich für Science-Fiction, Backen und Radfahren.