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

Leistungsüberraschungen und Annahmen :NOCOUNT EINSTELLEN

Wenn Sie schon einmal Management Studio verwendet haben, wird Ihnen diese Ausgabemeldung wahrscheinlich bekannt vorkommen:

(1 Zeile (n) betroffen)

Dies kommt von DONE_IN_PROC von SQL Server Nachricht, die bei erfolgreichem Abschluss einer beliebigen SQL-Anweisung gesendet wird, die ein Ergebnis zurückgegeben hat (einschließlich des Abrufs eines Ausführungsplans, weshalb Sie zwei dieser Nachrichten sehen, wenn Sie tatsächlich nur eine einzige Abfrage ausgeführt haben).

Sie können diese Meldungen mit folgendem Befehl unterdrücken:

SET NOCOUNT ON;

Warum würdest du das tun? Weil diese Nachrichten gesprächig sind und oft nutzlos . In meinen Präsentationen zu schlechten Angewohnheiten und Best Practices spreche ich oft über das Hinzufügen von SET NOCOUNT ON; für alle gespeicherten Prozeduren und Aktivieren im Anwendungscode, der Ad-hoc-Abfragen sendet. (Während des Debuggens möchten Sie jedoch vielleicht ein Flag, um die Meldungen wieder einzuschalten, da die Ausgabe in diesen Fällen nützlich sein kann.)

Ich habe immer den Haftungsausschluss hinzugefügt, dass der Rat, diese Option überall einzuschalten, nicht universell ist; es hängt davon ab, ob. ADO-Datensätze der alten Schule interpretierten diese tatsächlich als Ergebnissätze, sodass das nachträgliche Hinzufügen zu den Abfragen tatsächlich Anwendungen beschädigen könnte, die sie bereits manuell überspringen. Und einige ORMs (Husten NHibernate Husten ) analysieren die Ergebnisse tatsächlich, um den Erfolg von DML-Befehlen zu bestimmen (pfui!). Bitte testen Sie Ihre Änderungen.

Ich weiß, dass ich mir irgendwann selbst bewiesen hatte, dass diese gesprächigen Nachrichten die Leistung beeinträchtigen können, insbesondere über ein langsames Netzwerk. Aber es ist lange her, und letzte Woche fragte mich Erin Stellato, ob ich es jemals offiziell dokumentiert hätte. Ich habe nicht, also hier geht es. Wir nehmen eine sehr einfache Schleife, in der wir eine Tabellenvariable millionenfach aktualisieren:

SET NOCOUNT OFF;
 
DECLARE @i INT = 1;
DECLARE @x TABLE(a INT);
INSERT @x(a) VALUES(1);
 
SELECT SYSDATETIME();
 
WHILE @i < 1000000
BEGIN
  UPDATE @x SET a = 1;
  SET @i += 1;
END
 
SELECT SYSDATETIME();

Ein paar Dinge, die Ihnen vielleicht auffallen:

  • Der Nachrichtenbereich wird mit Instanzen des (1 row(s) affected) überschwemmt Botschaft:

  • Der anfängliche SELECT SYSDATETIME(); wird erst im Ergebnisbereich angezeigt, wenn der gesamte Stapel abgeschlossen ist. Das liegt an der Überschwemmung.
  • Die Ausführung dieses Stapels dauerte etwa 21 Sekunden.

Wiederholen wir dies nun ohne DONE_IN_PROC Nachrichten, indem Sie SET NOCOUNT OFF; ändern zu SET NOCOUNT ON; und führen Sie es erneut aus.

Während der Nachrichtenbereich nicht mehr mit den betroffenen Zeilen überschwemmt wurde, dauerte die Ausführung des Stapels immer noch ~21 Sekunden.

Dann dachte ich, Moment mal, ich weiß, was los ist. Ich befinde mich auf einem lokalen Computer ohne Netzwerk und verwende Shared Memory. Ich habe nur SSD und jede Menge RAM …

Also wiederholte ich die Tests mit meiner lokalen Kopie von SSMS gegen eine entfernte Azure SQL-Datenbank – ein Standard, S0, V12. Diesmal dauerten die Abfragen viel länger, selbst nachdem die Iterationen von 1.000.000 auf 100.000 reduziert wurden. Aber auch hier gab es keinen greifbaren Unterschied in der Leistung, ob DONE_IN_PROC Nachrichten gesendet wurden oder nicht. Beide Batches dauerten etwa 104 Sekunden, und dies war über viele Iterationen hinweg wiederholbar.

Schlussfolgerung

Jahrelang hatte ich den Eindruck, dass SET NOCOUNT ON; war ein kritischer Bestandteil jeder Performance-Strategie. Dies basierte auf Beobachtungen, die ich wohl in einer anderen Ära gemacht hatte und die sich heute wahrscheinlich nicht mehr manifestieren.

Trotzdem werde ich weiterhin SET NOCOUNT ON verwenden , auch wenn es auf heutiger Hardware keinen merklichen Leistungsunterschied gibt. Ich bin immer noch ziemlich stark daran interessiert, den Netzwerkverkehr so ​​weit wie möglich zu minimieren. Ich sollte in Betracht ziehen, einen Test zu implementieren, bei dem ich eine viel eingeschränktere Bandbreite habe (vielleicht hat jemand eine AOL-CD, die er mir leihen kann?) ist keine potenzielle Auswirkung in Worst-Case-Szenarien. Während es in der Zwischenzeit die wahrgenommene Leistung Ihrer Anwendung möglicherweise nicht ändert, kann es Ihrer Brieftasche dennoch helfen, diese festgelegte Option immer zu aktivieren, insbesondere in Situationen wie Azure – wo Ihnen möglicherweise Gebühren für ausgehenden Datenverkehr in Rechnung gestellt werden.