Dlaczego szybkość wykonywania instrukcji zależy od połączenia sieciowego?

31

Wygląda na to, że szybkość wykonywania T-SQL zależy od opóźnienia połączenia sieciowego z serwerem. Założyłem, że jeśli SQL Server nie ma nic do zgłaszania klientowi, będzie po prostu działał, dopóki nie zostanie wykonane, ale testy pokazują inną historię.

create procedure UselessLoop
  @I int
as
declare @D datetime = getdate()
while @I > 0 set @I -= 1
print datediff(millisecond, @D, getdate())

exec UselessLoop 100000

Server    Milliseconds
local     53
nearby    63
faraway   660

exec UselessLoop 1000000

Server    Milliseconds
local     546
nearby    640
faraway   6183

Testy są wykonywane na tym samym serwerze z różnych komputerów za pomocą SSMS. Lokalny jest wykonywany z serwera, w pobliżu jest w tej samej sieci lokalnej, a daleki jest wykonywany z innego biura 500 km połączonego 1 gigabitowym włóknem.

Oczywiście między programem SQL Server a klientem zachodzi pewna komunikacja, która zależy bezpośrednio od liczby wykonanych instrukcji.

Użyłem Wiresharka, aby zobaczyć, co jest transportowane i nie mogę powiedzieć, że tak dużo rozumiem, ale był to tcp.stream wymieniający w sumie 26 MB w 22740 pakietach.

Co powiesz na bezużyteczną funkcję?

create function dbo.UDFUselessLoop(@I int)
returns int
as
begin
  declare @D datetime = getdate()
  while @I > 0 set @I -= 1
  return datediff(millisecond, @D, getdate())
end

print dbo.UDFUselessLoop(1000000)

Wykonuje się w 406 milisekundach bez względu na to, skąd jest wykonywany. Wygląda na to, że w pętli nie ma komunikacji z klientem.

Mikael Eriksson
źródło
3
Zobacz też tę odpowiedź na moje pytanie, proszę stackoverflow.com/a/1547539
gbn

Odpowiedzi:

33

Oczywiście między programem SQL Server a klientem zachodzi pewna komunikacja, która zależy bezpośrednio od liczby wykonanych instrukcji.

Tak jest. Domyślnie program SQL Server wysyła komunikat TDSDONE_IN_PROC po każdej instrukcji w procedurze przechowywanej. Komunikat przekazuje klientowi informacje o statusie i liczbie wierszy dla zakończonej instrukcji.

Możesz zablokować wysyłanie tych wiadomości za pomocą polecenia T-SQL:

SET NOCOUNT ON;

Poniżej znajduje się fragment (mój nacisk) z pozycji Books Online dla tego polecenia:

W przypadku procedur składowanych, które zawierają kilka instrukcji, które nie zwracają zbyt dużej ilości danych rzeczywistych, lub procedur zawierających pętle języka Transact-SQL, ustawienie SET NOCOUNT na ON może zapewnić znaczne zwiększenie wydajności, ponieważ ruch sieciowy jest znacznie zmniejszony.

Powiązane pytania i odpowiedzi: Dlaczego prosta pętla powoduje, że ASYNC_NETWORK_IO czeka?

Paul White mówi GoFundMonica
źródło