Kee*_*ker 7 t-sql sql-server performance
有时我需要检查是否存在至少一条记录,通常我使用:
IF EXISTS (SELECT TOP 1 1 FROM [SomeTable] WHERE [Fields] = [Values]) BEGIN
-- action
END
Run Code Online (Sandbox Code Playgroud)
有没有快速的方法来检查是否存在多个记录?我可以这样做:
IF EXISTS (SELECT 1 FROM [SomeTable]
WHERE [Fields] = [Values]
HAVING Count(*) > 1)
BEGIN
-- action
END
Run Code Online (Sandbox Code Playgroud)
但我不确定这是否是最快的方式,因为它将测试集合中的所有记录.有更快的方法吗?
'where'部分可能非常复杂,可能包含多个AND和OR.
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)
Run Code Online (Sandbox Code Playgroud)
该TOP 2迭代器将停止请求行返回第二个之后,从而使内部查询到带有短路早期,而不是返回所有这些,对其计数.
两个版本的示例计划如下
关于评论中的问题
"你怎么知道哪一个最好?这是查询成本吗?"
在上述计划中显示的特定情况下,成本将是一个合理的指示,因为估计和实际行计数非常准确,并且除了添加TOP迭代器之外,两个计划非常相似.因此,计划中显示的额外成本完全表示需要扫描额外数量的行(并且可能从光盘读入)并计算.
在这种情况下,很明显这只是代表了额外的工作.在其他计划中它可能不是.添加TOP 2可能会显着改变它下面的查询树(例如,使用阻塞迭代器的不利计划)
在这种情况下,执行计划中显示的成本可能不是可靠的指标.即使在实际执行计划中,所显示的成本也基于估计,因此仅与那些一样好,即使估计的行数很好,所显示的成本仍然只是基于某些建模假设.
SQL Kiwi 在DBA网站上最近的回答中说得很好
优化程序成本估算主要仅用于内部服务器目的.即使在"高水平",它们也不打算用于评估潜在的表现.该模型是一种抽象,恰好可以很好地用于其设计的内部目的.估计成本与硬件和配置上的实际执行成本有任何明显相似之处的可能性非常小.
根据对您来说重要的实际问题,选择其他指标来比较效果.
逻辑读取(显示在何时SET STATISTICS IO ON;)是可以查看的一个这样的度量,但再次关注这一点可能会产生误导.测试查询持续时间可能是唯一可靠的方法,但即使这不是一个精确的科学,因为性能可能会根据服务器上的并发活动而变化(等待内存授予,可用的DOP,缓存中的相关页面数).
最后,它只是得到一个查询计划,该计划看起来是对服务器上资源的有效利用.