为什么 SQL Server 在执行查询时会返回一些行,有时不会?

Rac*_*SQL 34 sql-server ssms

有一些查询,当我们点击“执行”时,它会显示一些行并不断增长,但查询还没有结束。但有时,它会等到查询结束。

为什么会发生这种情况?有没有办法控制这个?

Eri*_*ing 45

像往常一样(好吧,大部分时间),答案在于执行计划。

有些操作符要求所有行都到达它们,然后才能开始处理这些行,并将它们传递到下游,例如:

  • Hash Join(关于构建哈希表)
  • 哈希匹配
  • 排序(Hash Flow Distinct 除外)

因此,它们要么被称为阻塞操作符,要么被称为“走走停停”操作符,当优化器认为必须处理大量数据才能找到数据时,通常会选择它们。

还有其他运算符可以开始流式传输,或立即传递任何找到的行

  • 嵌套循环
  • 索引支持的合并连接
  • 流聚合

当查询立即开始返回数据但没有立即完成时,通常表明优化器选择了一个计划来使用启动成本较低的运算符快速定位和返回一些行。

这可能是因为您或优化器引入的行目标。

如果由于某种原因(缺乏 SARGability、参数嗅探、统计数据不足等)选择了一个糟糕的计划,也会发生这种情况,但这需要更多的挖掘才能弄清楚。

有关更多信息,请在此处查看 Rob Farley 的博客

保罗怀特的连续进球系列在这里这里这里这里

还应该注意的是,如果您谈论的是 SSMS,则行仅在整个缓冲区填满后才会出现,而不仅仅是随意。


Aar*_*and 14

如果我明白你在观察什么,这就是 Management Studio呈现行的方式,与 SQL Server返回行的方式无关。事实上,通常当您将大型结果返回给 SSMS 并尝试在网格中呈现它们时,SSMS 无法跟上,并且 SQL Server 最终会等待应用程序处理更多行。在这种情况下,您将看到 SQL Server 累积ASYNC_NETWORK_IO等待。

您可以通过使用结果转文本而不是结果转网格来稍微控制它,因为 SSMS 可以比绘制网格更快地绘制文本,但是您可能会发现这会影响可读性,具体取决于所涉及的列数和数据类型。两者都受到 SSMS 决定实际将结果写入该窗格的时间的影响,这取决于输出缓冲区的满度。

当您有多个语句,并且想要强制缓冲区将输出结果呈现到消息窗格时,您可以在语句之间使用一些打印技巧:

RAISERROR('', 0, 1) WITH NOWAIT;
Run Code Online (Sandbox Code Playgroud)

但是,当所有输出都来自单个语句时,当您试图让 SSMS 更快地呈现行时,这将无济于事。

更直接的是,您可以通过限制在 SSMS 中呈现的结果数量来控制它。我经常看到人们抱怨将一百万行返回到网格需要多长时间。我不知道任何人会用 SSMS 网格中的一百万行来做什么。

有一些 hacks 之类的OPTION (FAST 100),它将优化检索前 100 行(或任何 100 行,如果没有外ORDER BY),但这可能以对其余行的检索速度慢得多和计划更多总体上效率低下,所以恕我直言,这并不是一个真正的首选。