看来执行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与SQL Server之间存在一些通信。客户端直接取决于执行的语句数。

我使用Wireshark来查看传输的内容,我不能说我理解得太多,但这是一个tcp.stream交换了总计22740数据包中26 MB的数据。

无用的函数又如何呢?

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毫秒内执行,无论它在哪里从执行。看起来循环中没有与客户端的通信。

评论

也在我的问题上看到这个答案,请stackoverflow.com/a/1547539

#1 楼


很明显,SQL Server和客户端之间正在进行某些通信,而这些通信直接取决于所执行的语句数。


是的。默认情况下,SQL Server在存储过程中的每个语句之后发送TDS DONE_IN_PROC消息。该消息将已完成语句的状态和行计数信息传达给客户端。

您可以使用T-SQL命令禁止发送这些消息:

SET NOCOUNT ON;

下面是此命令的联机丛书摘录(重点):


对于包含多个不会返回大量实际数据的语句的存储过程,或者对于包含Transact-SQL循环的过程,将SET NOCOUNT设置为ON可以显着提高性能,因为大大减少了网络流量。


相关问答:为什么ASYNC_NETWORK_IO等待中的简单循环结果?