Почему скорость выполнения операторов зависит от сетевого подключения?

31

Похоже, что скорость выполнения T-SQL зависит от задержки сетевого соединения с сервером. Я предположил, что если SQL Server не будет о чем сообщить клиенту, он просто будет выполняться до тех пор, пока это не будет сделано, но тестирование покажет другую историю.

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

Тесты выполняются на одном и том же сервере с разных компьютеров с использованием SSMS. Локальный выполняется с сервера, рядом находится в той же локальной сети, а удаленный выполняется из другого офиса в 500 км, соединенного с 1 гигабитным волокном.

Очевидно, что между SQL Server и клиентом происходит некоторая связь, которая напрямую зависит от количества выполненных операторов.

Я использовал Wireshark, чтобы посмотреть на то, что транспортируется, и я не могу сказать, что я это понимаю, но это был tcp.stream, который обменивался в общей сложности 26 МБ в 22740 пакетах.

Как насчет бесполезной функции вместо этого?

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)

Он выполняется за 406 миллисекунд независимо от того, откуда он выполняется. Похоже, что нет связи с клиентом в цикле.

Микаэль Эрикссон
источник
3
Смотрите этот ответ и на мой вопрос, пожалуйста, stackoverflow.com/a/1547539
gbn

Ответы:

33

Очевидно, что между SQL Server и клиентом происходит некоторая связь, которая напрямую зависит от количества выполненных операторов.

Да, есть. По умолчанию SQL Server отправляет сообщение TDSDONE_IN_PROC после каждого оператора в хранимой процедуре. В сообщении клиенту передается информация о состоянии и количестве строк для выполненного оператора.

Вы можете запретить отправку этих сообщений с помощью команды T-SQL:

SET NOCOUNT ON;

Ниже приведен отрывок (мой акцент) из записи Books Online для этой команды:

Для хранимых процедур, которые содержат несколько операторов, которые не возвращают много фактических данных, или для процедур, которые содержат циклы Transact-SQL, установка SET NOCOUNT в положение ON может обеспечить значительное повышение производительности, поскольку сетевой трафик значительно уменьшается.

Связанные вопросы и ответы: почему простой цикл приводит к ожиданию ASYNC_NETWORK_IO?

Пол Уайт говорит, что GoFundMonica
источник