Database
 sql >> Datenbank >  >> RDS >> Database

Warte Statistik und Abfragespeicher

Es gibt zahlreiche Blog-Posts auf dieser Seite, die sich auf Wartestatistiken beziehen; Sie sind eine der wichtigsten Metriken, die Sie bei der Problembehandlung von Leistungsproblemen in SQL Server verwenden können. Wartestatistiken wurden in SQL Server 2005 verfügbar gemacht und traditionell haben sie Wartezeiten auf Instanzebene über sys.dm_os_wait_statistics dargestellt. Diese Informationen sind bei der Fehlerbehebung bei der Systemleistung im Allgemeinen großartig, aber bei der Betrachtung der Abfrageleistung konnten Warteinformationen nur gesehen werden, wenn die Abfrage ausgeführt wurde und wenn sie über sys.dm_os_waiting_tasks auf eine Ressource wartete. Die Daten in sys.dm_os_waiting_tasks sind vorübergehend (was gerade wartet) und sind nicht einfach zu erfassen und für die Lebensdauer einer Abfrage für eine spätere Leistungsoptimierung aufzubewahren.

In SQL Server 2016 wird eine neue DMV bereitgestellt, sys.dm_exec_session_wait_stats, die Informationen zu Wartezeiten für eine vorhandene, aktive Sitzung bereitstellt. Wenn Sie die session_id kennen, können Sie Wartezeiten auf eine Abfrage nachverfolgen, wenn sie beginnt und wenn sie abgeschlossen ist (Momentaufnahme der Informationen am Anfang und am Ende der Abfrage und Vergleichen der Informationen). Die Herausforderung besteht darin, dass Sie die session_id für die Abfrage kennen und die Datenerfassung im Voraus einrichten müssen – was nicht trivial ist, wenn Sie sich mitten in einem Problem mit hoher Priorität befinden.

Wartestatistikinformationen sind in einem tatsächlichen Ausführungsplan ab SQL Server 2016 SP1 vorhanden. Nur die 10 häufigsten Wartezeiten werden erfasst, und es gibt Einschränkungen hinsichtlich der Darstellung dieser Daten. Beispielsweise wird CXPACKET ignoriert und nicht in die Ausgabe aufgenommen, aber es wird in 2016 SP2 und 2017 CU3 und höher enthalten sein – wo irrelevante Parallelitätswartezeiten stattdessen von CXCONSUMER erfasst werden (die nicht in den tatsächlichen Planwartezeiten enthalten sind).

Wie können wir also sehen, worauf eine bestimmte Abfrage wirklich wartet? Wir können Query Store verwenden! SQL Server 2017 umfasst die Erfassung von Wartestatistikinformationen im Abfragespeicher, und diese Funktionalität ist auch in Azure SQL-Datenbank verfügbar. Wartestatistiken sind an einen Abfrageplan gebunden und werden im Laufe der Zeit erfasst, genau wie die Laufzeitstatistiken. Das Hinzufügen von Wartestatistikinformationen im Abfragespeicher war die häufigste Funktionsanforderung nach seiner ersten Veröffentlichung, und all diese Informationen zusammen schaffen leistungsstarke Fehlerbehebungsfunktionen.

Erste Schritte

Die Erfassung von Wartestatistiken im Abfragespeicher ist standardmäßig für Azure SQL-Datenbank aktiviert. Wenn eine neue Datenbank in SQL Server 2017 erstellt oder eine Datenbank von SQL Server 2014 oder früher aktualisiert wird, ist der Abfragespeicher standardmäßig deaktiviert … und somit ist die Erfassung von Wartestatistiken deaktiviert. Wenn eine Datenbank von SQL Server 2016 aktualisiert wird und der Abfragespeicher aktiviert ist, wird die Erfassung von Wartestatistiken für den Abfragespeicher beim Upgrade aktiviert.

Zu Demonstrationszwecken habe ich die WideWorldImporters-Datenbank wiederhergestellt und dann die folgenden Abfragen ausgeführt, um den Abfragespeicher zu aktivieren und alle möglicherweise zuvor vorhandenen Daten zu löschen (nur erforderlich, da dies eine Beispieldatenbank ist):

ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON;
GO
 
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE 
(
  OPERATION_MODE = READ_WRITE
);
GO
 
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR;
GO

Die Standardeinstellungen werden mit den obigen Anweisungen verwendet, und wenn Sie eine der Optionen ändern möchten, können Sie dies über die Benutzeroberfläche oder über die ALTER DATABASE-Anweisung tun. Nachdem der Abfragespeicher nun aktiviert ist, beginnt er mit der Erfassung von Abfragedaten, einschließlich des Abfragetexts, der Pläne, Laufzeitstatistiken und Wartestatistiken.

Ansehen der Wartestatistik

Um einige Daten zu generieren, erstellen wir eine gespeicherte Prozedur, die wiederholt eine parallele Abfrage ausführt.

DROP PROCEDURE IF EXISTS [Sales].[OrderInfo];
GO
 
CREATE PROCEDURE [Sales].[OrderInfo]
AS
BEGIN
  WHILE 1=1
  BEGIN
    SELECT *
      FROM Sales.OrderLines ol
      INNER JOIN Warehouse.StockItems s
      ON ol.StockItemID = s.StockItemID
      OPTION (QUERYTRACEON 8649);
  END
END

Erstellen Sie dann eine .cmd-Datei mit dem folgenden Code:

start sqlcmd -S WIN2016\SQL2017 -d WideWorldImporters -q"EXECUTE [Sales].[OrderInfo];"
exit

Dadurch können wir nicht Führen Sie den SP in Management Studio aus, wodurch erhebliche ASYNC_NETWORK_IO-Wartezeiten entstehen. Wir möchten die Wartezeiten im Zusammenhang mit Parallelität sehen. Speichern Sie die .cmd-Datei und doppelklicken Sie dann, um sie auszuführen. Sie können zusätzliche Last erzeugen, indem Sie mehrere Dateien ausführen. Bei diesem Szenario sehen wir hauptsächlich die Wartezeiten im Zusammenhang mit dieser Abfrage, da wir keine andere Arbeitslast haben. Fühlen Sie sich frei, gleichzeitig andere Abfragen für die WideWorldImporters-Datenbank auszuführen, wenn Sie noch mehr Wartedaten generieren möchten.

Beenden Sie nach einigen Minuten die Befehlsdateien und erweitern Sie die WideWorldImporters-Datenbank in Management Studio, um den Ordner „Abfragespeicher“ und die darunter liegenden Berichte anzuzeigen. Wenn Sie den Bericht „Top-Ressourcen verbrauchende Abfragen“ öffnen, sollten Sie die Abfrage der gespeicherten Prozedur als die Top-Abfrage sehen.

Die Standardansicht für diesen Bericht zeigt Abfragen mit der höchsten Gesamtdauer. Um Abfragen basierend auf Wartestatistiken anzuzeigen, können wir die Schaltfläche „Konfigurieren“ auswählen und sie in „Wartezeit (ms)“ ändern.

Schaltfläche "Konfigurieren" in der Berichtsansicht (oben rechts) Ändern der Ressource für den Bericht Beachten Sie, dass Sie auch das Zeitintervall und die Anzahl der zurückgegebenen Abfragen konfigurieren können. Für dieses Beispiel ist die letzte Stunde akzeptabel.

Wenn Sie den Mauszeiger über den Balken für die erste Abfrage bewegen, sehen Sie die Wartezeiten für die Abfrage. Diese Ansicht ist derzeit die einzige Möglichkeit, die Warteinformationen in der Benutzeroberfläche anzuzeigen, aber zusätzliche Berichte speziell für Wartestatistiken werden hoffentlich in einer zukünftigen Version von Management Studio erscheinen.

Warteinformationen in der Benutzeroberfläche

Diejenigen von Ihnen, die eine Weile mit Wartestatistiken gearbeitet haben, werden feststellen, dass die Beschreibungen der Wartetypen unterschiedlich sind. Das heißt, anstelle eines CXPACKET-Wartetyps zur Angabe der Parallelität sehen Sie einfach „Parallelism Wait Type“. Dies ist ein grundlegender Unterschied im Query Store:Die Wartetypen sind in Kategorien gruppiert. Derzeit gibt es in SQL Server über 900 verschiedene Wartetypen, und der Versuch, jeden einzeln zu verfolgen, ist extrem teuer. Darüber hinaus wurde der Abfragespeicher für alle Datenfachleute entwickelt – egal, ob Sie ein Experte für Leistungsoptimierung sind oder gerade erst anfangen, die Funktionsweise von SQL Server zu verstehen, Sie sollten in der Lage sein, den Abfragespeicher zu verwenden, um Abfragen mit schlechter Leistung leicht zu finden. Das bedeutet auch, die Warteinformationen verständlicher zu machen. Eine vollständige Liste der Wartekategorien und der darin enthaltenen Wartetypen finden Sie in der Dokumentation zu sys.query_store_wait_stats.

Sie können Warteinformationen auch mit T-SQL anzeigen. Eine Beispielabfrage ist die folgende, die die Abfrage, die plan_id(s) für diese Abfrage und Wartestatistiken für ein bestimmtes Zeitintervall enthält:

SELECT TOP (10)
  [ws].[wait_category_desc],
  [ws].[avg_query_wait_time_ms],
  [ws].[total_query_wait_time_ms],
  [ws].[plan_id],
  [qt].[query_sql_text],
  [rsi].[start_time],
  [rsi].[end_time]
FROM [sys].[query_store_query_text] [qt]
JOIN [sys].[query_store_query] [q]
    ON [qt].[query_text_id] = [q].[query_text_id]
JOIN [sys].[query_store_plan] [qp] 
    ON [q].[query_id] = [qp].[query_id]
JOIN [sys].[query_store_runtime_stats] [rs] 
    ON [qp].[plan_id] = [rs].[plan_id]
JOIN [sys].[query_store_runtime_stats_interval] [rsi] 
    ON [rs].[runtime_stats_interval_id] = [rsi].[runtime_stats_interval_id]
JOIN [sys].[query_store_wait_stats] [ws]
    ON [ws].[runtime_stats_interval_id] = [rs].[runtime_stats_interval_id]
    AND [ws].[plan_id] = [qp].[plan_id]
WHERE [rsi].[end_time] > DATEADD(MINUTE, -5, GETUTCDATE()) 
AND [ws].[execution_type] = 0
ORDER BY [ws].[avg_query_wait_time_ms] DESC;

Abfrageausgabe

Während Sie jetzt alle Wartezeiten für eine bestimmte Abfrage und ihren Plan sehen können, müssen Sie sich noch weiter mit der Leistung befassen, um beispielsweise zu verstehen, warum eine Abfrage parallel ausgeführt wird (wenn Sie dies vielleicht nicht möchten) oder was könnte eine Abfrage blockieren. Beachten Sie, dass die Wartestatistiken ebenso wie die Laufzeitstatistiken im Laufe der Zeit an den Abfrageplan gebunden sind. In dieser Ausgabe ist die Intervalllänge für den Abfragespeicher auf 10 Minuten festgelegt, sodass die Wartezeitstatistiken für jeden Plan für dieses 10-Minuten-Intervall gelten (23:50 Uhr am 21. November 2017 bis Mitternacht am 22. November 2017). Standardmäßig beträgt die Intervalllänge beim Aktivieren des Abfragespeichers 60 Minuten.

Zusammenfassung

Wartestatistiken in Kombination mit individuellen Abfrageplänen machen den Abfragespeicher zu einem noch beeindruckenderen Tool bei der Fehlerbehebung bei der System- und Abfrageleistung. Der Abfragespeicher ist die einzige Funktion, mit der Sie Abfragen, Pläne, Leistungsmetriken und Wartestatistiken nativ an einem Ort erfassen können. Für diejenigen unter Ihnen, die an die unzähligen Wartetypen gewöhnt sind, sollte die Anpassung an die im Abfragespeicher verwendeten Kategorien nahtlos sein. Für alle, die neu in Wartestatistiken sind, sind die Kategorien ein großartiger Ort, um zu verstehen, auf welche Ressource eine Abfrage wartet.