如果不需要,SQL Server 是不是足够聪明,不会执行昂贵的查询? (短路)

Posted

技术标签:

【中文标题】如果不需要,SQL Server 是不是足够聪明,不会执行昂贵的查询? (短路)【英文标题】:Will SQL Server be smart enough to not execute expensive queries if it is not needed ? (short-circuiting)如果不需要,SQL Server 是否足够聪明,不会执行昂贵的查询? (短路) 【发布时间】:2020-08-06 14:28:13 【问题描述】:

因此,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 行除外。不需要时是否会评估子查询?

如果有人有类似的真实案例,只要在没有 99.99% 的子查询的情况下快速获取结果,就可以让 0.01% 的人等待昂贵的子查询运行后再获得结果的案例。 (我知道我上面的具体示例可以使用 SP 中的 IF 语句显式处理,正如此相关线程中所建议的: Sql short circuit OR or conditional exists in where clause 但让我们假设这不是一个选项。)

【问题讨论】:

SQL 布尔运算符不保证短路,也不保证不短路。优化器可能会或可能不会根据执行计划的最终结果而忽略子句,而这又取决于许多其他因素,因此没有简单的答案。原则上,就语义而言,您必须假设它们不会短路。使用 CASE 比布尔运算符更可靠,但也不能 100% 保证省略不必要的子句(但仍然更加一致)。如果您需要性能,这可能是更好的选择。 您可能会争辩说,当所有行都相等someValue 时,不需要子查询,但即使不是,它也是需要的。如果你说你至少有一行不等于someValue,那么是的,它需要被执行,没有办法绕过它。无论如何,当所有行都是someValue 时,它很可能会被执行。如果它必须保留一个查询,请将其两个查询,= 'someValue'<> 'someValue' and (expensive)union all 的结果合二为一。但这仍然不能保证。 FWIW,我在您的问题中运行了代码,其中子查询引用了一个没有有用索引的大表。大表从未接触过 3 行“someValue”,因为该计划包含一个启动表达式过滤器以进行短路。 YMMV 取决于许多因素,因此无法一概而论。 @DanGuzman 感谢所有的 cmets,非常有趣。在我的实际情况下,“昂贵的子查询”并不是那么昂贵,所以我只是走简单的路线,因为性能损失可以忽略不计,但它激发了我的好奇心。最好记住不要总是相信执行计划来解决我猜想的最佳方法 如果执行计划不够聪明,无法制定出来,它可能有助于创建索引、统计信息或约束以提供足够的线索。 【参考方案1】:

正如 cmets 所指出的,SQL Server 中的优化器非常聪明。

您可以使用case 尝试短路。正如documentation 所说:

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 替换IN 并使用适当的索引可能会消除子查询的几乎所有性能损失。但是,那是另一回事。

【讨论】:

以上是关于如果不需要,SQL Server 是不是足够聪明,不会执行昂贵的查询? (短路)的主要内容,如果未能解决你的问题,请参考以下文章

关于视图和索引 (SQL Server 2008 R2)

sql server 统计信息

RestKit / Core Data / Offline - 我需要 UUID 还是 RestKit 足够聪明?

JDBC SQL Server十进制“发明”精度

java JDBC sql server 判断一条信息是不是已存在表中,如果不存在则添加,如果存在则更新重要字段

excel与sql server各自的优点与缺点