Jeśli kiedykolwiek korzystałeś z Management Studio, ten komunikat wyjściowy prawdopodobnie będzie wyglądał znajomo:
(1 wiersz(e) dotknięte)
Pochodzi z DONE_IN_PROC
programu SQL Server wiadomość, która jest wysyłana po pomyślnym zakończeniu dowolnej instrukcji SQL, która zwróciła wynik (w tym pobranie planu wykonania, dlatego widzisz dwie z tych wiadomości, gdy faktycznie wykonałeś tylko jedno zapytanie).
Możesz wyłączyć te wiadomości za pomocą następującego polecenia:
SET NOCOUNT ON;
Dlaczego chcesz to zrobić? Ponieważ te wiadomości są rozmowne i często bezużyteczne . W moich prezentacjach dotyczących złych nawyków i najlepszych praktyk często mówię o dodaniu SET NOCOUNT ON;
do wszystkich procedur składowanych i włączania go w kodzie aplikacji przesyłającej zapytania ad hoc. (Podczas debugowania możesz jednak chcieć flagi, aby ponownie włączyć komunikaty, ponieważ dane wyjściowe mogą być przydatne w takich przypadkach.)
Zawsze dodawałem zastrzeżenie, że rada, aby włączyć tę opcję wszędzie, nie jest uniwersalna; to zależy. Staroświeckie zestawy rekordów ADO faktycznie zinterpretowały je jako zestawy wyników, więc dodanie ich do zapytań po fakcie może faktycznie zepsuć aplikacje, które już ręcznie je pomijają. I niektóre ORM (kaszel NHibernate kaszel ) faktycznie analizuje wyniki, aby określić powodzenie poleceń DML (ugh!). Przetestuj zmiany.
Wiem, że w pewnym momencie udowodniłem sobie, że te gadatliwe wiadomości mogą wpływać na wydajność, szczególnie w wolnej sieci. Ale minęło dużo czasu, aw zeszłym tygodniu Erin Stellato zapytała mnie, czy kiedykolwiek formalnie to udokumentowałam. Nie mam, więc zaczynam. Weźmiemy bardzo prostą pętlę, w której zaktualizujemy zmienną tabeli milion razy:
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();
Kilka rzeczy, które możesz zauważyć:
- Okienko wiadomości jest zalane instancjami
(1 row(s) affected)
wiadomość: - Początkowy
SELECT SYSDATETIME();
pojawia się w okienku wyników dopiero po zakończeniu całej partii. Dzieje się tak z powodu powodzi. - Uruchomienie tej partii zajęło około 21 sekund.
Teraz powtórzmy to bez DONE_IN_PROC
wiadomości, zmieniając SET NOCOUNT OFF;
do SET NOCOUNT ON;
i uruchom go ponownie.
Chociaż okienko wiadomości nie było już zalewane wiadomościami, których dotyczyły wiersze, uruchomienie partii nadal trwało ~21 sekund.
Potem pomyślałem, chwileczkę, wiem o co chodzi. Pracuję na komputerze lokalnym, bez udziału sieci, używam pamięci współdzielonej, mam tylko dysk SSD oraz duże i duże ilości pamięci RAM…
Powtórzyłem więc testy przy użyciu mojej lokalnej kopii SSMS względem zdalnej bazy danych Azure SQL — Standard, S0, V12. Tym razem zapytania trwały znacznie dłużej, nawet po zmniejszeniu iteracji z 1 000 000 do 100 000. Ale znowu nie było namacalnej różnicy w wydajności, niezależnie od tego, czy DONE_IN_PROC
wiadomości były wysyłane, czy nie. Obie partie zajęły około 104 sekund i było to powtarzalne w wielu iteracjach.
Wniosek
Przez lata działałem pod wrażeniem, że SET NOCOUNT ON;
był krytyczną częścią każdej strategii wydajności. Było to oparte na obserwacjach, które poczyniłem prawdopodobnie w innej epoce i które są mniej prawdopodobne dzisiaj.
To powiedziawszy, będę nadal używać SET NOCOUNT ON
, nawet jeśli na dzisiejszym sprzęcie nie ma zauważalnej różnicy w wydajności. Nadal bardzo mocno zależy mi na minimalizowaniu ruchu sieciowego tam, gdzie to możliwe. Powinienem rozważyć wdrożenie testu, w którym mam znacznie bardziej ograniczoną przepustowość (może ktoś ma płytę AOL, którą może mi pożyczyć?) lub mieć maszynę, na której ilość pamięci jest mniejsza niż limity bufora wyjściowego Management Studio, aby mieć pewność, że istnieje nie jest potencjalnym wpływem w najgorszych scenariuszach. W międzyczasie, chociaż może to nie zmienić postrzeganej wydajności Twojej aplikacji, nadal może pomóc Twojemu portfelowi zawsze włączać tę ustawioną opcję, szczególnie w sytuacjach takich jak Azure – gdzie możesz zostać obciążony za ruch wychodzący.