Por que a velocidade de execução das instruções depende da conexão de rede?

31

Parece que a velocidade de execução do T-SQL depende da latência da conexão de rede com o servidor. Presumi que, se o SQL Server não tiver nada a relatar ao cliente, ele será executado apenas até que seja concluído, mas o teste mostra outra história.

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

Os testes são executados no mesmo servidor em computadores diferentes usando o SSMS. Local é executado a partir do servidor, próximo fica na mesma rede local e distante é executado a partir de outro escritório a 500 km de distância, conectado com 1 gigabit de fibra.

Obviamente, existe alguma comunicação entre o SQL Server e o cliente que depende diretamente do número de instruções executadas.

Eu usei o Wireshark para ver o que é transportado e não posso dizer que compreendo muito, mas foi um tcp.stream trocando um total de 26 MB em 22740 pacotes.

Que tal uma função inútil?

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)

Ele é executado em 406 milissegundos, independentemente de onde é executado. Parece que não há comunicação com o cliente no loop.

Mikael Eriksson
fonte
3
Veja esta resposta na minha pergunta também, por favor stackoverflow.com/a/1547539
gbn

Respostas:

33

Obviamente, existe alguma comunicação entre o SQL Server e o cliente que depende diretamente do número de instruções executadas.

Sim existe. Por padrão, o SQL Server envia uma mensagem TDSDONE_IN_PROC após cada instrução em um procedimento armazenado. A mensagem comunica ao cliente informações de status e contagem de linhas da instrução concluída.

Você pode suprimir o envio dessas mensagens usando o comando T-SQL:

SET NOCOUNT ON;

A seguir, uma extração (ênfase minha) da entrada do Books Online para este comando:

Para procedimentos armazenados que contêm várias instruções que não retornam muitos dados reais ou para procedimentos que contêm loops Transact-SQL, definir SET NOCOUNT como ON pode fornecer um aumento significativo no desempenho, porque o tráfego de rede é bastante reduzido.

Perguntas e respostas relacionadas: Por que um loop simples resulta em esperas ASYNC_NETWORK_IO?

Paul White diz que a GoFundMonica
fonte