SQL 服务器是否足够智能以在不需要时不执行昂贵的查询? (短路)
Will SQL Server be smart enough to not execute expensive queries if it is not needed ? (short-circuiting)
因此 SQL 服务器不会像通用编程语言中的 if 语句那样以显式方式进行短路。
因此请考虑以下模拟查询:
SELECT * FROM someTable
WHERE name = 'someValue' OR name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*)
假设 table 中只有 3 行,并且所有行都匹配 name = 'someValue'。昂贵的子查询会 运行 吗?
假设有 300 万行,除 1 行之外的所有行都可以使用名称 = 'someValue' 获取,除了 1 行需要使用子查询获取。子查询在不需要时会被评估吗?
如果一个人有类似的真实案例,那么只要在没有子查询的情况下快速获取结果,就可以让 0.01% 等待昂贵的子查询 运行 然后再获取结果-查询99.99%的案例。
(我知道我上面的具体示例可以用 SP 中的 IF 语句显式处理,如相关线程中所建议的那样:
Sql short circuit OR or conditional exists in where clause
但我们假设这不是一个选项。)
正如评论所指出的,SQL 服务器中的优化器非常智能。
您可以尝试使用 case
进行短路。正如 documentation 所述:
The CASE
expression evaluates its conditions sequentially and stops with the first condition whose condition is satisfied.
请注意,有一些涉及聚合的例外情况。所以,你可以这样做:
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_
函数修复。
在您的情况下,我怀疑将 IN
替换为 EXISTS
并使用适当的索引可能会消除子查询的几乎所有性能损失。不过,那就另当别论了。
因此 SQL 服务器不会像通用编程语言中的 if 语句那样以显式方式进行短路。
因此请考虑以下模拟查询:
SELECT * FROM someTable
WHERE name = 'someValue' OR name in (*some extremely expensive nested sub-query only needed to cover 0.01% of cases*)
假设 table 中只有 3 行,并且所有行都匹配 name = 'someValue'。昂贵的子查询会 运行 吗? 假设有 300 万行,除 1 行之外的所有行都可以使用名称 = 'someValue' 获取,除了 1 行需要使用子查询获取。子查询在不需要时会被评估吗?
如果一个人有类似的真实案例,那么只要在没有子查询的情况下快速获取结果,就可以让 0.01% 等待昂贵的子查询 运行 然后再获取结果-查询99.99%的案例。 (我知道我上面的具体示例可以用 SP 中的 IF 语句显式处理,如相关线程中所建议的那样: Sql short circuit OR or conditional exists in where clause 但我们假设这不是一个选项。)
正如评论所指出的,SQL 服务器中的优化器非常智能。
您可以尝试使用 case
进行短路。正如 documentation 所述:
The
CASE
expression evaluates its conditions sequentially and stops with the first condition whose condition is satisfied.
请注意,有一些涉及聚合的例外情况。所以,你可以这样做:
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_
函数修复。
在您的情况下,我怀疑将 IN
替换为 EXISTS
并使用适当的索引可能会消除子查询的几乎所有性能损失。不过,那就另当别论了。