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

Bandbreitenfreundliches Abfrageprofil für Azure SQL-Datenbank

SQL Server hat schon immer die Möglichkeit geboten, Live-Abfragen auf Ad-hoc-Basis in einem leicht konsumierbaren Rowset-Format zu erfassen – zunächst mit dem Legacy-SQL Server Profiler, später über Extended Events in SSMS. Diese Funktion ist bei der Leistungsoptimierung wertvoll, da Abfrageereignisse diskrete CPU- und E/A-Metriken sowie Laufzeitparameter enthalten, die für die Fehlerbehebung bei Abfrageleistungsproblemen wie Parameter-Sniffing von entscheidender Bedeutung sind. Darüber hinaus enthalten Abfrageereignisse andere wichtige Elemente wie den Hostnamen des Clients, den Anwendungsnamen, die Anmeldung, die Windows-Prozess-ID usw.

Sie können immer aggregiert abrufen Leistungsmetriken für normalisiert Abfragen von DMVs oder dem Abfragespeicher, aber sie enthalten nur kompiliert Parameter und keines der vorgenannten Elemente. Dies ist zwar hilfreich, aber nicht dasselbe. Wenn Sie beispielsweise die spezifische Parameterkombination sehen möchten, die von dieser Abfrage verwendet wird, die 2 Milliarden Lesevorgänge ausgeführt hat, oder die Anwendung mit dem höchsten CPU-Verbrauch in den letzten 24 Stunden finden möchten, haben Sie Pech.

Azure SQL-Datenbank wird vom Legacy-Profiler nicht unterstützt, und Microsoft hat den XEvents-Streaminganbieter (sys.fn_MSxe_read_event_stream TVF) aus Gründen der Zuverlässigkeit deaktiviert, sodass Sie mit SSMS keine XE-Sitzung starten und „Livedaten ansehen“ können. Query Performance Insights im Azure-Portal wird vom Query Store unterstützt, sodass Sie wieder nur die normalisierten Abfragen und aggregierten Leistungsdaten haben, nicht die tatsächlichen Abfrageereignisse.

Also steckten wir ein paar Jahre fest – die einzige Option für die Profilerstellung von Azure SQL-Datenbank bestand darin, manuell eine XEvents-Ablaufverfolgung zu erstellen, die mit Azure Storage in einen Ringpuffer oder ein Dateiziel schreibt, was beides nicht optimal ist. Die Verwendung des Ringpuffers mit T-SQL-Abfragen kann aufgrund der von Jonathan Kehayias hier behandelten 4-MB-Grenze für formatiertes XML problematisch sein, und Dateiziele erfordern eine Menge Umwege und zusätzliche Kosten. Beide erfordern eine manuelle Abfrage der XE-Daten und sind daher nicht gerade "live" im herkömmlichen Sinne.

Geben Sie Neu ein SQL Server Profiler

Als ich von der SQL Server Profiler-Erweiterung für Azure Data Studio erfuhr, war ich erfreut zu sehen, dass Microsoft endlich eine grafische Lösung für die Live-Abfrageerfassung in Azure SQL-Datenbank liefert. Leider war meine Aufregung aus mehreren Gründen nur von kurzer Dauer.

Erstens wurde der gefürchtete „Standard“-Trace des alten Profilers offenbar als Modell für die ADS Profiler XE-Sitzung für die Azure SQL-Datenbank verwendet , benannt ADS_Standard_Azure standardmäßig. (Die für den vollständigen SQL Server verwendeten XE-Sitzungen sind ähnlich.) Wie ich vor einigen Jahren gebloggt habe und immer noch glaube, ist der Standard-Trace einer der Hauptgründe dafür, dass Legacy-Profiler so schlecht angesehen werden. Es enthält mehrere nutzlose und nicht filterbare Ereignisse wie SQL-Batch-Start , anmelden und abmelden , und als Ergebnis bringt es keinen wirklichen Mehrwert für die Leistungsoptimierung. Bei der synchronen Rowset-Ablaufverfolgungsarchitektur, die von Legacy-Profiler verwendet wird, kann sich das hohe Ereignisvolumen außerdem auf die Leistung ausgelasteter Systeme auswirken. Aus irgendeinem Grund wird dieses Ding nicht verschwinden!

Legacy Profiler „Standard“ Ablaufverfolgungsereignisse

ADS Profiler „ADS_Standard_Azure“ XE-Ereignisse
– kommt Ihnen das bekannt vor?

Zweitens verwendet es einen Ringpuffer mit einer maximalen Größe von 8 MB oder 1000 Ereignissen, je nachdem, was zuerst eintritt. Da die Anmelde-/Abmeldeereignisse klein sind, werden Sie oft 1000 Ereignisse erreichen, lange bevor Sie die 8-MB-Grenze oder sogar die 4-MB-Grenze für formatiertes XML erreichen. Bei einer moderaten Mischung von SQL-Ereignissen beträgt der XML-Ringpuffer bei 1000 Ereignissen in meinen Tests jedoch immer noch 2 bis 3 MB, und das Problem besteht darin, dass dieser gesamte Puffer jedes Mal über das Netzwerk gezogen wird, wenn die Profiler-Erweiterung eine Abfrage zur Aktualisierung durchführt sein Gitter , was je 1 Sekunde oder Dauer der vorherigen Umfrage länger ist. Das XML wird dann clientseitig von der ADS-Profiler-Erweiterung geparst, um festzustellen, welche Ereignisse seit der letzten Abfrage neu sind, und die neuen Ereignisse werden dem Raster hinzugefügt.

Der Ringpuffer füllt sich sogar auf einem mäßig ausgelasteten Server fast sofort, und der Nettoeffekt ist, dass Sie schnell>40 Megabit pro Sekunde aus Ihrer Azure SQL-Datenbank über das Netzwerk ziehen werden . Dies entspricht 300 Megabyte pro Minute oder 18 Gigabyte pro Stunde!

Netzwerktreffer von der ADS-Profiler-Erweiterung (4-Minuten-Bereich)

Meine anfängliche Befürchtung war, dass dies zu enormen Gebühren für ausgehenden Datenverkehr auf der nächsten Azure-Rechnung führen könnte. Wenn wir uns jedoch unsere eigenen Azure-Abonnements ansehen, konnten wir nicht bestätigen, dass der Netzwerkdatenverkehr für Azure SQL DB berechnet wird. Mike Wood (b|t), ein Azure MVP von SentryOne, versuchte wochenlang, die Antwort zu finden, und erhielt schließlich von Microsoft die Nachricht, dass Netzwerkausgang derzeit tatsächlich nicht für Azure SQL DB berechnet wird, obwohl sich dies jederzeit ändern könnte. Trotzdem scheint es nicht verantwortungsvoll zu sein, 18 GB Abfragedaten pro Stunde zu verlieren, und könnte Ihrer nächsten Netflix-Binge-Watching-Session sicherlich einen Dämpfer versetzen.

Obwohl Sie über die Profiler-Benutzeroberfläche Filter festlegen können, die die Überprüfung der Daten erleichtern, wird die Netzwerkbelastung dadurch nicht verringert, da sie clientseitig ausgeführt werden.

Eine aktualisierte XE-Sitzung

Eine schnelle Lösung, um die Netzwerklast von ADS Profiler zu reduzieren und die Daten für die Optimierung der Abfrageleistung viel brauchbarer zu machen, besteht darin, ADS_Standard_Azure zu aktualisieren XE-Sitzung. Unten ist ein Skript, das Folgendes tun wird:

  • Löschen Sie die nutzlosen Ereignisse:

    • sqlserver.attention
    • sqlserver.existing_connection
    • sqlserver.login
    • sqlserver.logout
    • sqlserver.sql_batch_starting
  • Legen Sie einen Schwellenwert für die Dauer> 1 Sekunde (1000000 Mikrosekunden) für die verbleibenden Ereignisse fest:

    • sqlserver.rpc_completed
    • sqlserver.sql_batch_completed
  • Reduzieren Sie die maximale Größe des Ringpuffers von 1000 auf 10 Ereignisse

    • Dies würde niemals mit dem Original-Trace funktionieren, da 10 Ereignisse in Millisekunden generiert werden und der Ringpuffer zu schnell recycelt würde, wodurch die meisten Ereignisse verloren gehen würden. Mit dem 1-Sekunden-Dauerfilter ist der Ereignisfluss jedoch viel geringer, und 10 Ereignisse sollten mit dem vom ADS-Profiler verwendeten Abfrageintervall von 1 Sekunde gut funktionieren.
ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
DROP EVENT sqlserver.attention,
DROP EVENT sqlserver.existing_connection,
DROP EVENT sqlserver.login,
DROP EVENT sqlserver.logout,
DROP EVENT sqlserver.rpc_completed,
DROP EVENT sqlserver.sql_batch_completed,
DROP EVENT sqlserver.sql_batch_starting
GO
 
ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
ADD EVENT sqlserver.rpc_completed(
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id,sqlserver.username)
      WHERE (([package0].[equal_boolean]([sqlserver].[is_system],(0))) AND ([duration] >= (1000000)))),
ADD EVENT sqlserver.sql_batch_completed(
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id,sqlserver.username)
      WHERE (([package0].[equal_boolean]([sqlserver].[is_system],(0))) AND ([duration] >= (1000000))))
GO
 
ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
DROP TARGET package0.ring_buffer
GO
 
ALTER EVENT SESSION [ADS_Standard_Azure] ON DATABASE 
ADD TARGET package0.ring_buffer(SET max_events_limit=(10),max_memory=(51200))
GO

Nach Anwendung des Skripts zur Aktualisierung der XE-Sitzung wird die Firehose sofort auf ein Rinnsal reduziert:

Reduzierter Netzwerkzugriff nach Aktualisierung der ADS Profiler XE-Sitzung

Noch leichtere Alternativen

SQL Sentry und sein SaaS-Pendant SentryOne Monitor sind die einzigen anderen mir bekannten Lösungen zum Erfassen von Abfragen aus der Azure SQL-Datenbank, und sie verwenden dabei einen innovativen Ansatz, der erheblich leichter ist als die oben genannte optimierte XE-Sitzung für ADS Profiler. Neben anderen erweiterten Funktionen können Sie ganz einfach nach Client-Hostname, Anwendung und Anmeldung aggregieren und mit dem integrierten Plan-Explorer automatisch Abfragepläne zur Analyse erfassen.

SentryOne Monitor zeigt erfasste Abfragen und Pläne aus der Azure SQL-Datenbank

Schließen

Microsoft hat erklärt, dass sie die ADS Profiler-Erweiterung weiter verbessern werden, und wenn sie dies tun, hoffe ich, dass sie die oben beschriebenen Probleme angehen werden. Ich habe das Problem hier geloggt. In der Zwischenzeit sorgt das aktualisierte Skript für eine sicherere und bandbreitenfreundlichere Abfrageprofilerstellung für Azure SQL-Datenbank.