SQL Server是否足够智能,在不需要时不执行昂贵的查询?(短路)

SQL Server是否足够智能,在不需要时不执行昂贵的查询?(短路),sql,sql-server,short-circuiting,short-circuit-evaluation,Sql,Sql Server,Short Circuiting,Short Circuit Evaluation,因此,SQL Server不像通用编程语言中的if语句那样具有显式短路 考虑下面的模拟查询: SELECT * FROM someTable WHERE name = 'someValue' OR name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*) 假设表中只有3行,它们都匹配name='someValue'。昂贵的子查询是否会运行? 假设有300万行,除了1行之外,

因此,SQL Server不像通用编程语言中的if语句那样具有显式短路

考虑下面的模拟查询:

SELECT * FROM someTable
WHERE name = 'someValue' OR name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*)
假设表中只有3行,它们都匹配name='someValue'。昂贵的子查询是否会运行? 假设有300万行,除了1行之外,其他所有行都可以使用name='someValue'获取,只有1行需要使用子查询获取。子查询在不需要时会被计算吗

如果您有一个类似的实际案例,那么您可以让0.01%等待昂贵的子查询运行,然后再获取结果,只要结果是快速获取的,而不需要对99.99%的案例执行子查询。 (我知道,我上面的具体示例可以通过SP中的IF语句显式处理,正如本相关线程中所建议的:
但是让我们假设这不是一个选项。)

正如评论所指出的,SQL Server中的优化器非常智能

您可以使用
案例
尝试短路。作为缔约国:

CASE
表达式按顺序计算其条件,并使用满足条件的第一个条件停止

请注意,有些例外情况涉及聚合。因此,你可以:

SELECT t.*
FROM someTable t
WHERE 'true' = (CASE WHEN t.name = 'someValue' THEN 'true'
                     WHEN t.name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*)
                     THEN 'true'
                END)
这种强制排序通常被认为是一个坏主意。一个例外是当其中一个路径可能涉及错误时,例如类型转换错误)——然而,这在现在的
try\函数中通常是固定的


在您的情况下,我怀疑将
中的
替换为
EXISTS
并使用适当的索引可能会消除子查询的几乎所有性能损失。但是,这是另一回事。

SQL布尔运算符不能保证短路,也不能保证不能短路。优化器可以省略子句,也可以不省略子句,这取决于执行计划的最终结果,而执行计划的最终结果又取决于许多其他因素,因此没有简单的答案。原则上,就语义而言,您必须假设它们不会短路。使用
CASE
比布尔运算符更可靠,但也不能100%保证省略不必要的子句(但仍然更加一致)。如果您需要性能,这可能是一个更好的选择。您可能会争辩说,当所有行都相等时,不需要子查询
someValue
,但即使其中一行不相等,也需要子查询。如果您说至少有一行不等于
someValue
,那么是的,需要执行它,没有办法。尽管如此,它很可能在所有行都是
someValue
时执行。如果必须保留单个查询,则将其设置为两个查询,分别为
='someValue'
'someValue'和(昂贵)
,以及
将所有结果合并为一个查询。但是这仍然不能保证。FWIW,我运行了您问题中的代码,子查询引用了一个没有有用索引的大表。由于计划中包含一个用于短路的启动表达式筛选器,因此大表从未接触过3个“someValue”行。YMMV取决于许多因素,因此行为无法概括。@DanGuzman感谢大家的评论,非常有趣。在我的实际案例中,“昂贵的子查询”实际上并没有那么昂贵,所以我选择了简单的方法,因为性能损失是可以忽略的,但它激发了我的好奇心。记住这些很好不要总是相信执行计划能够以最好的方式解决问题我猜如果执行计划不够聪明,无法解决问题,那么创建索引、统计或约束可能会有助于提供足够的线索。