SQL Server 通常不会短路聚合查询。有时它可以将查询转换为使用与(在此处的评论中讨论的HAVING COUNT(*) > 0
)相同的计划,但仅此而已。EXISTS
查询将HAVING COUNT(*) > 1
始终计算所有行,即使理论上它可能会在第 2 行之后停止计数。
考虑到这一点,我会使用
IF EXISTS(
SELECT * FROM (
SELECT TOP 2 *
FROM [SomeTable]
WHERE [Fields] = [Values]
) T
HAVING COUNT(*)=2)
迭代器将在TOP 2
返回第二个行后停止请求行,从而允许内部查询提前短路,而不是全部返回并计算它们。
两个版本的示例计划如下
关于评论中的问题
“你怎么知道哪个最好?是查询成本吗?”
在计划中显示的特定情况下,成本将是一个合理的指示,因为估计的和实际的行数非常准确,并且两个计划非常相似,除了添加了TOP
迭代器。因此,计划中显示的额外成本完全表示需要扫描(并且可能从磁盘读取)并计算额外数量的行。
在这种情况下,很明显,这只是代表额外的工作。在其他计划中可能不是。添加TOP 2
可能会显着改变它下面的查询树(例如,不喜欢带有阻塞迭代器的计划)
在这种情况下,执行计划中显示的成本可能不是一个可靠的指标。即使在实际执行计划中,显示的成本也是基于估计的,因此仅与那些一样好,即使估计的行数很好,显示的成本仍然只是基于某些建模假设。
SQL Kiwi在 DBA 网站上的这个最近的回答中很好地说明了这一点
优化器成本估算主要仅对内部服务器有用。它们不是用来评估潜在性能的,即使是在“高水平”。该模型是一种抽象,恰好可以很好地用于其设计的内部目的。估计成本与硬件和配置上的实际执行成本有任何明显相似之处的可能性确实非常小。
根据对您来说重要的任何实际问题,选择其他指标来比较性能。
逻辑读取(在 时显示SET STATISTICS IO ON;
)是一种可以查看的指标,但再次专注于这一点可能会产生误导。测试查询持续时间可能是唯一可靠的方法,但即使这也不是一门精确的科学,因为性能可能会因服务器上的并发活动而异(等待内存授予、可用 DOP、缓存中相关页面的数量)。
最后,它只是归结为获得一个看起来可以有效利用服务器上资源的查询计划。