SQL-Performance untersuchen? Metriken und Query Store prüfen

Ein Auslastungsdiagramm zeigt, wann Datenbankressourcen beschäftigt waren. Query Store ergänzt SQL-Anweisungen, Ausführungspläne und Laufzeitstatistiken, mit denen du beteiligte Abfragen untersuchen kannst. Vergleiche beide Ansichten für dasselbe Zeitfenster.

Verwende die Lab-Datenbank sqldb-cloudtrips aus Azure SQL Database erstellen oder erstelle sie erneut, falls sie gelöscht wurde. Melde dich im Query editor als SQL-Administrator an und erlaube deine aktuelle Client-IP in der Serverfirewall. Führe die Übung in der Lab-Datenbank aus.

Auslastung prüfen

Öffne sqldb-cloudtrips → Monitoring → Metrics. Wähle Last hour, eine Minute Granularität und vergleiche CPU percentage, Data IO percentage und Log IO percentage. Average zeigt den Verlauf, Maximum hilft bei kurzen Spitzen.

Vergleiche CPU, Daten-IO und Log-IO, um die belastete Ressource zu erkennen. Eine ruhige Datenbank kann bei dieser kleinen Übung nahe null bleiben.

Screenshot 1: Datenbankauslastung mit ausgewähltem Zeitfenster und CPU-/IO-Messwerten.

Datenbankauslastung mit ausgewähltem Zeitfenster und CPU-/IO-Messwerten.

Kleine Abfrage-Workload erfassen

Führe im Query editor aus:

SELECT actual_state_desc, query_capture_mode_desc
FROM sys.database_query_store_options;

Erwartet wird READ_WRITE. Notiere den Capture-Modus, normalerweise AUTO. Ist Query Store OFF, aktiviere ihn mit ALTER DATABASE CURRENT SET QUERY_STORE = ON;. Bei READ_ONLY prüfst du zuerst Konfiguration und verfügbaren Speicher.

Stelle für dieses kurze Lab den Capture-Modus auf ALL, damit auch eine kleine, günstige Abfrage erfasst wird. Erstelle eine eigene Testtabelle und führe die markierte Abfrage zehnmal aus:

ALTER DATABASE CURRENT SET QUERY_STORE (QUERY_CAPTURE_MODE = ALL);

IF OBJECT_ID(N'dbo.ct_monitor_probe', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.ct_monitor_probe (n int NOT NULL PRIMARY KEY);
    INSERT dbo.ct_monitor_probe (n)
    SELECT TOP (10000)
        CONVERT(int, ROW_NUMBER() OVER (ORDER BY a.object_id, b.object_id))
    FROM sys.all_objects AS a CROSS JOIN sys.all_objects AS b;
END;

DECLARE @i int = 0;
WHILE @i < 10
BEGIN
    EXEC sys.sp_executesql N'/* CloudTrips_SQL_Monitor */
        SELECT SUM(CONVERT(bigint, n)) AS total
        FROM dbo.ct_monitor_probe WHERE n % 7 = 0;';
    SET @i += 1;
END;
EXEC sys.sp_query_store_flush_db;

Stelle direkt danach den notierten Capture-Modus wieder her. Für den üblichen AUTO-Wert:

ALTER DATABASE CURRENT SET QUERY_STORE (QUERY_CAPTURE_MODE = AUTO);

Stelle ihn auch wieder her, falls die Workload fehlschlägt. War er zuvor ALL, NONE oder CUSTOM, verwende diesen ursprünglichen Wert. Die Übung erzeugt erkennbare Abfragehistorie; zehn kleine Abfragen können im Auslastungsdiagramm kaum sichtbar sein.

Abfrage-Performance untersuchen

Öffne Intelligent Performance → Query Performance Insight der Datenbank und wähle einen Zeitraum mit dem Test. Prüfe CPU, Ausführungsanzahl und Dauer. Wähle anschließend eine Abfrage, um ihren Text zu sehen. Für dieses Diagramm können einige Stunden erfasster Historie nötig sein.

Für eine unmittelbare Untersuchung führst du im Query editor aus:

SELECT TOP (10)
    q.query_id,
    p.plan_id,
    SUM(rs.count_executions) AS executions,
    CAST(
        SUM(rs.avg_duration * rs.count_executions)
        / NULLIF(SUM(rs.count_executions), 0)
        / 1000.0
        AS decimal(18,2)
    ) AS average_ms,
    CAST(
        SUM(rs.avg_cpu_time * rs.count_executions)
        / NULLIF(SUM(rs.count_executions), 0)
        / 1000.0
        AS decimal(18,2)
    ) AS average_cpu_ms,
    MAX(rs.last_execution_time) AS last_execution,
    qt.query_sql_text
FROM sys.query_store_query_text AS qt
JOIN sys.query_store_query AS q
    ON q.query_text_id = qt.query_text_id
JOIN sys.query_store_plan AS p
    ON p.query_id = q.query_id
JOIN sys.query_store_runtime_stats AS rs
    ON rs.plan_id = p.plan_id
WHERE qt.query_sql_text LIKE N'%ct[_]monitor[_]probe%'
  AND qt.query_sql_text NOT LIKE N'%sys.query[_]store[_]%'
GROUP BY
    q.query_id,
    p.plan_id,
    qt.query_sql_text
ORDER BY executions DESC;

Diese Abfrage findet erfasste Anweisungen mit ct_monitor_probe und schließt die Query-Store-Inspektionsabfragen selbst aus. Sie durchsucht die gesamte aufbewahrte Historie, sodass auch ein älterer Test sichtbar bleibt. Die Ergebnisse können das INSERT für die Tabelle und frühere Testläufe enthalten. Identifiziere das Test-SELECT anhand von query_sql_text und wähle mit last_execution den passenden Zeitraum im Metrikdiagramm.

Die Berechnung gewichtet den Durchschnitt jedes Intervalls mit dessen Ausführungszahl und rechnet Mikrosekunden in Millisekunden um. Summen und Durchschnittswerte umfassen die aufbewahrten Laufzeitstatistiken je Abfrage und Plan.

Screenshot 2: Query-Store-Ergebnisse mit dem Test-SELECT auf ct_monitor_probe, Query-/Plan-IDs, Ausführungsanzahl und Dauer. Wenn Query Performance Insight bereits Daten anzeigt, kann dort dieselbe Untersuchung dargestellt werden.

Query-Store-Ergebnisse mit dem Test-SELECT auf ct_monitor_probe, Query-/Plan-IDs, Ausführungsanzahl und Dauer. Wenn Query Performance Insight bereits Daten anzeigt, kann dort dieselbe Untersuchung dargestellt werden.

Duration enthält verstrichene Wartezeit; CPU time misst Prozessorarbeit. Eine häufige günstige Abfrage kann insgesamt mehr Ressourcen verbrauchen als eine seltene teure. Untersuche Abfragetext, Pläne, Wartezeiten und Indizes, bevor du eine größere Datenbank auswählst.

Abschluss

Entferne die Testtabelle mit DROP TABLE IF EXISTS dbo.ct_monitor_probe; und prüfe den wiederhergestellten Capture-Modus. Lass Query Store für weitere Beobachtung aktiviert oder stelle den ursprünglich deaktivierten Zustand wieder her, falls du ihn nur für dieses Lab eingeschaltet hast. Behalte oder lösche die SQL-Lab-Ressourcen passend zu deinen weiteren SQL-Übungen.