在某些查询中,当我们单击“执行”时,它显示一些行并且还在不断增长,但是查询尚未结束。但有时,它会等到查询结束。

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

#1 楼

答案(通常,通常是大多数情况)取决于执行计划。

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


哈希联接(在构建哈希表时)
哈希匹配
排序(哈希流区别除外)

因此,它们被称为阻塞或停止操作,通常在优化器认为必须处理大量数据才能找到数据时才选择它们。 />还有其他运算符可以开始流式处理,或立即沿行传递任何找到的行

支持索引的合并合并
流聚合
/>
当查询开始立即返回数据但又没有立即完成时,通常表明优化器选择了使用启动成本较低的运算符快速定位并返回某些行的计划。

发生这种情况的原因可能是您或优化器引入了行目标。

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

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

以及Paul White的关于行列目标的系列。那就是,如果您在谈论SSMS,则只有在整个缓冲区被填满后才出现行,而不仅仅是willy-nilly。

#2 楼

如果我了解您的观察,这就是Management Studio呈现行的方式,与SQL Server返回行的方式无关。实际上,通常当您将较大的结果返回给SSMS并尝试将其呈现在网格中时,SSMS无法跟上,并且SQL Server最终等待应用程序处理更多行。在这种情况下,您会看到SQL Server累积了ASYNC_NETWORK_IO等待。您可能会发现这会影响可读性,具体取决于列数和所涉及的数据类型。当SSMS决定将结果实际写到该窗格时,两者都会受到影响,这取决于输出缓冲区的容量。

当您有多个语句时,您想强制缓冲区呈现输出结果显示在“消息”窗格中,您可以在语句之间使用一些打印技巧:当所有输出均来自单个语句时,行可以更快地排成一行。

更直接地,您可以通过限制要在SSMS中呈现的结果数来控制它。我经常看到人们抱怨将一百万行返回到网格需要多长时间。地球上任何人都打算在SSMS网格中处理一百万行,我不知道。行(如果没有外部OPTION (FAST 100)),但这会以其余行的检索慢得多且整体计划效率较低的代价为代价,因此实际上不是IMHO的首选。 >

#3 楼

您的问题与SQLServer本身无关,而是:


SQLServer
网络
SSMS作为客户端应用程序



/>有办法控制此方法吗? of sqlcmd

检查您的连接和会话设置

长答案:

当然!但不是一个-prob


ssms或在qs中以sqlcmd -mode执行查询。
如果要排除网络角色,请在具有共享内存连接的服务器上运行查询。如果查询无法通过网络执行-请致电您的网络网络管理员以寻求帮助。如果您的查询仅在SSMS中执行不佳-请进一步阅读。
现在,我们确定问题出在客户端(在这种情况下为SSMS)。查看SSMS中的连接和会话设置。不要相信ssms界面并使用SQL Profiler进行检查:通过ssms找到您的连接,您会获得会话设置的完整列表。与sqlcmd会话的设置进行比较。如果没有点击-将所有会话设置从事件探查器复制到查询脚本中,以sqlcmd -mode执行并逐步切换设置,您将发现自己的罪魁祸首。

祝你好运!

#4 楼

要添加到sp_BlitzErik的答案中,请使用带有子选择的NOT IN ()作为示例。为了确定某个项目是否在嵌套查询的结果中,通常需要检索整个结果。

所以我找到了一种简单的方法来提高此类查询的性能是将它们重写为LEFT OUTER JOIN,其中RIGHT边的条件为空(您当然可以将其翻转,但是谁使用RIGHT OUTER JOINS吗?)。这样就可以立即开始返回结果。

评论


我不这么认为。如果比较的列不可为空,那么对于3个版本的抗连接(不插入,不存在,左连接/为空),结果应该相同并且计划(通常)相同。不必检索整个结果。

–超立方体ᵀᴹ
18年4月13日在17:20

如果子选择是一个非常复杂的子查询,则生成的查询需要先检查整个子选择,然后再检查NOT IN条件,即WHERE tx IN(<复杂选择子查询>),等效的左联接,左联接(<复杂选择子查询>) AS r ON rx = tx...。如果rx为NULL,则也必须对子查询进行评估(与NOT IN版本相同的复杂计划)。

–超立方体ᵀᴹ
18年4月13日在17:24

@ypercubeᵀᴹ过去对我有用。我已经看到查询从花费几分钟到返回亚秒级。

– JimmyJames
18年4月13日在18:02

@ypercubeᵀᴹ我在Oracle中整理了一个简单的示例(很抱歉,目前我无法访问SQLServer),他们肯定有不同的解释计划。也许它们不是有意义的差异,但看起来却大不相同。

– JimmyJames
18年4月13日在19:49

@JimmyJames:如果要稳定的性能,这不是一个简单的方法,并且这种“优化”对于SQLServer版本非常敏感。而且不要误解吸引Oracle(哪个版本?)。从历史上看,SQLServer在查询中更喜欢NOT EXISTS,而Oracle NOT IN。但是今天,它必须被视为计划生成器中的错误

–于Yu
18年4月14日在12:14