Eine der größten Herausforderungen in SQL Server ist die Behebung von Problemen mit der Parameterempfindlichkeit oder Kardinalitätsschätzung, die zu Leistungseinbußen bei einer Arbeitsauslastung führen. Im Allgemeinen benötigen Sie den tatsächlichen Ausführungsplan der ausgeführten Anweisung, um die Ursache der Leistungsminderung ermitteln zu können. In SQL Server 2012 bietet das erweiterte Ereignis query_post_execution_showplan die Möglichkeit, den tatsächlichen Ausführungsplan für Anweisungen zu erfassen. So nützlich dies auch scheint, dieses Ereignis kann jedoch nicht ohne erhebliche Leistungseinbußen bei der auf dem Server ausgeführten Arbeitslast verwendet werden.
In meinem Artikel „Measurement „Observer Overhead“ of SQL Trace vs. Extended Events“ habe ich einen Vergleich der Leistungsauswirkungen von SQL Trace mit einer identischen Konfiguration unter Verwendung von Extended Events in SQL Server 2012 gezeigt. Zu der Zeit, als ich ursprünglich die Tests für diesen Artikel durchgeführt habe Ich habe auch das Ereignis query_post_execution_showplan in SQL Server 2012 ausgiebig getestet. Dieses Ereignis wurde erstmals in SQL Server 2012 CTP1 eingeführt, als viele der Ablaufverfolgungsereignisse auf erweiterte Ereignisse portiert wurden, um eine Parität mit der SQL-Ablaufverfolgung bereitzustellen. Zu diesem Zeitpunkt hatte das Ereignis nur eine Teilmenge der Spalten, die in der endgültigen RTM von SQL Server 2012 enthalten waren.
Während CTP1 habe ich ein Connect-Element übermittelt, in dem ich angefordert habe, dass eine Aktion erstellt wird, um die Erfassung des tatsächlichen Ausführungsplans mit Ereignissen in SQL Server 2012 zu ermöglichen. Das Ziel war es, die Ereignisse module_end oder sql_statement_completed verwenden zu können, um die Ausführung einer Prozedur zu identifizieren oder Aussage ihre normale Dauer überschreitet. Beispielsweise kann im Szenario der Parametersensitivität, in dem ein weniger idealer Plan für die normalen Parameterwerte generiert wird, das Ereignis verwendet werden, um den tatsächlichen Ausführungsplan für diese Anweisung durch eine Aktion zu erfassen. Als Reaktion darauf fügte das SQL Server-Team die Spalten „duration“ und „cpu_time“ zum Ereignis „query_post_execution_showplan“ hinzu, damit Prädikatdefinitionen dieses Ereignis nur für diese Szenarien erfassen können.
Leider hat dies nicht die gleichen Vorteile, die eine Implementierung als Aktion für die Leistung gehabt hätte. Im Rest dieses Beitrags werde ich erklären, warum.
Auswirkungen auf die Leistung
Als ich die Tests für meinen vorherigen Artikel durchführte, testete ich auch den mit dem Ereignis query_post_execution_showplan verbundenen Overhead, hauptsächlich weil ich wirklich daran interessiert war, es in einigen Client-Produktionssystemen zu verwenden, und bevor ich dies tat, musste ich verstehen, was Art der Auswirkungen, die das Ereignis auf ihre Arbeitsbelastung haben würde. Ich war wirklich bestürzt über die Ergebnisse meiner ursprünglichen Tests, und nachdem Aaron Bertrand meine Ergebnisse mit dem internen Testrahmen von SQL Sentry validiert hatte, reichte ich ein weiteres Connect-Element ein, in dem die Leistungsprobleme gemeldet wurden, das anschließend als „By Design“ geschlossen wurde. .
Zum Testen der Auswirkungen auf die Leistung wurde genau die gleiche Workload- und Distributed Replay-Konfiguration aus dem Artikel „Measuring „Observer Overhead“ of SQL Trace vs. Extended Events“ verwendet. Der einzige Unterschied zu den in diesem Artikel gezeigten Testergebnissen besteht darin, dass für die VM-Umgebung ein neueres, leistungsfähigeres Hostsystem verwendet wurde. Die verwendeten VMs waren ohne Änderungen an ihrer Konfiguration genau gleich und wurden einfach auf das neue System kopiert, weshalb die Baseline-Workload die Wiedergabe schneller mit höheren durchschnittlichen Batch-Anforderungen/Sek. durchführen konnte. Die Baseline-Ergebnisse wurden mit einer Standardinstallation von SQL Server 2012 erfasst, wobei nur die standardmäßige system_health-Ereignissitzung auf dem Server ausgeführt wurde.
Für den Vergleich der Leistungsauswirkung des query_post_execution_showplan
Ereignis wurde die folgende Ereignissitzungsdefinition verwendet.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan( WHERE ([duration]=(5000000))); GO
Diese Sitzung sammelt die Ereignisdaten nicht tatsächlich unter Verwendung eines Ziels und verwendet ein Prädikat für die Dauer, da die Ereignisdauer gleich 5000000 Mikrosekunden oder einer Dauer von fünf Sekunden ist. Bei der Arbeitslast für die Wiedergabe hat keine ausgeführte Anweisung eine Dauer von genau fünf Sekunden, sodass das Ereignis query_post_execution_showplan niemals tatsächlich auf dem Server ausgelöst wird und Leistungseinbußen ausschließlich das Ergebnis der Ereignisdatenerfassung und der anschließenden Prädikatauswertung sind. Die Ergebnisse der Tests sind in Tabelle 1 dargestellt und in Diagramm 2 grafisch dargestellt.
Tabelle 1 – query_post_execution-Ereignis-Overhead
Diagramm 2 – query_post_execution-Ereignis-Overhead
Für diese Testrunde verschlechtert sich die Leistung der Workload um etwa 30 %, indem dieses Ereignis einfach in einer Ereignissitzung aktiviert wird, obwohl es für keines der Ereignisse ausgelöst wird, die auf dem Server wiedergegeben werden. Die Gesamtverschlechterung hängt von der tatsächlichen Arbeitslast des Servers ab, und es ist wichtig zu beachten, dass diese Testreihe eher ein Worst-Case-Szenario widerspiegelt, da Distributed Replay im Belastungsmodus ausgeführt wurde und die CPU-Auslastung auf dem SQL Server festgelegt wurde bei durchschnittlich 94 % während der Tests.
Die Auswirkungen auf die Leistung verstehen
Der Grund dafür, dass dieses Ereignis einen so erheblichen Mehraufwand für die Leistung verursacht, lässt sich aus dem Ereignislebenszyklus in Erweiterte Ereignisse erklären. Wenn während der Ausführung ein kritischer Punkt im SQL Server-Code auftritt, der einem Ereignis zugeordnet ist, führt der Code eine sehr schnelle boolesche Prüfung durch, um festzustellen, ob das Ereignis in einer aktiven Ereignissitzung auf dem Server aktiviert ist. Wenn das Ereignis für eine aktive Ereignissitzung aktiviert ist, werden alle dem Ereignis zugeordneten Datenspalten erfasst, einschließlich aller anpassbaren Spalten, die aktiviert wurden. An diesem Punkt wertet das Ereignis alle Prädikate für die aktiven Ereignissitzungen aus, die das Ereignis erfassen, um festzustellen, ob das Ereignis tatsächlich vollständig ausgelöst wird.
Für das Ereignis query_post_exection_showplan stammt die gesamte Leistungsbeeinträchtigung aus dem Overhead, der mit der Datenerfassung verbunden ist. Selbst wenn ein Prädikat für eine Dauer von fünf Sekunden vorhanden ist, muss das Showplan-XML für jede Anweisung, die auf dem Server ausgeführt wird, einfach durch Einschalten des Ereignisses in einer Ereignissitzung erfasst werden, nur um das Prädikat auswerten zu können und stellen Sie dann fest, dass das Ereignis nicht ausgelöst wird. Aus diesem Grund sollte das Ereignis query_post_execution_showplan für Produktionsworkloads vermieden werden. Für die Test-Replay-Workload musste das Ereignis ungefähr 440.000 Mal ausgewertet werden, obwohl es für die zu testende Workload- und Ereignissitzung nicht tatsächlich ausgelöst wird, da keines der Replay-Ereignisse eine Dauer von genau fünf Sekunden hat. Die Informationen zur Ereignisanzahl wurden gesammelt, indem das Ziel event_counter zur Ereignissitzung hinzugefügt und das Prädikat für die Dauer entfernt wurde und dann die Arbeitslast der Wiedergabe mit der folgenden Sitzungsdefinition erneut getestet wurde.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan ADD TARGET package0.event_counter; GO
Vergleich mit schnell feuernden Ereignissen
Um einen Bezugsrahmen für diese Auswirkungen auf die Leistung bereitzustellen, können wir uns den Overhead ansehen, der entsteht, wenn eine Reihe von häufig ausgeführten Ereignissen auf dem Server aktiviert und dieselbe Wiederholungsarbeitslast ausgeführt wird. Zwei der am häufigsten ausgeführten Ereignisse in SQL Server sind die Ereignisse lock_acquired und lock_released. Um den Aufwand dieser beiden Ereignisse zu vergleichen, kann die folgende Ereignissitzung verwendet werden, die die Ereignisse ohne Prädikat sammelt, sodass jede Ausführung erfasst wird und zählt, wie oft sie ausgelöst werden, indem das event_counter-Ziel verwendet wird.
CREATE EVENT SESSION [locking Overhead] ON SERVER ADD EVENT sqlserver.lock_acquired, ADD EVENT sqlserver.lock_released ADD TARGET package0.event_counter; GO
Für unsere Wiederholungsarbeitslast werden diese beiden Ereignisse ungefähr 111.180.000 Mal ausgelöst. Der mit der Erfassung dieser Ereignisse verbundene Overhead ist in Tabelle 3 und Diagramm 4 ersichtlich.
Tabelle 3 – Locking-Overhead-Vergleich
Diagramm 4 – Overhead-Vergleich von Sperrereignissen
Wie Sie den Daten entnehmen können, ist der Leistungseffekt dieser Ereignisse deutlich geringer als bei query_post_execution_showplan, obwohl die Sitzungsdefinition für Sperrereignisse so konfiguriert war, dass alle Ereignisse auf dem Server ausgelöst werden konnten, lag der Gesamtaufwand insgesamt unter 1 % . Denken Sie daran, dass die Sperrereignissitzung das Äquivalent von 500-mal mehr Ereignissen ausgewertet hat und in diesem Fall alle Ereignisse tatsächlich für die Ereignissitzung ausgelöst werden mussten, während das Ereignis query_post_execution_showplan nach der Auswertung nicht wirklich ausgelöst werden musste.
Zusammenfassung
Während das Ereignis query_post_execution_showplan die Möglichkeit bietet, den tatsächlichen Abfrageplan für eine auszuführende Anweisung zu erfassen, macht die Leistungsauswirkung der Datenerfassung nur zum Auswerten des Ereignisses es zu etwas, das für die Verwendung in der Produktion nicht praktikabel ist. Der Overhead sollte zumindest berücksichtigt werden, bevor Sie dieses Ereignis jemals für eine Produktionsworkload verwenden. Sogar die von Microsoft bereitgestellte Ereignisbeschreibung erkennt an, dass das Ereignis erhebliche Auswirkungen auf die Leistung haben kann (meine Hervorhebung):
Tritt auf, nachdem eine SQL-Anweisung ausgeführt wurde. Dieses Ereignis gibt eine XML-Darstellung des tatsächlichen Abfrageplans zurück. Die Verwendung dieses Ereignisses kann zu erheblichen Leistungseinbußen führen, daher sollte es nur zur Fehlerbehebung oder kurzzeitigen Überwachung bestimmter Probleme verwendet werden.Die Ereignisbeschreibung finden Sie in der Beschreibungsspalte der sys.dm_xe_objects-Katalogansicht oder in der Benutzeroberfläche für neue Sitzungen, wie in Abbildung 5 (meine Hervorhebung) gezeigt:
Abbildung 5 – Ereignisbeschreibung von der Benutzeroberfläche „Neue Sitzung“
Ich würde empfehlen, die Leistung jedes Ereignisses mit dieser Warnung in der Beschreibung zu bewerten, bevor es tatsächlich in einer Produktionsumgebung verwendet wird.