强制 SQL Server 按照书面形式运行查询条件?

Roy*_*mir 15 sql-server optimization sql-server-2008-r2

我正在使用 SQL Server 2008 R2 并且我有这个伪查询 (SP):

select ...
from ...
WHERE    @LinkMode IS NULL
     AND (myColumn IN (...very long-running query...))
     ...
     ...
Run Code Online (Sandbox Code Playgroud)

问题是查询需要很长时间才能执行——即使我使用@LinkMode=2.

正如您所注意到的,只有当 @LinkMode 为 null 时才应该执行长时间运行的查询,而这里不是这种情况。在我的情况下 @LinkMode = 2 !

但是,如果我将其更改为:

 select ...
    from ...
    WHERE    1=2
         AND (myColumn IN (...very long time exeted query...))
     ...
     ...
Run Code Online (Sandbox Code Playgroud)

SP确实跑得很快。

我以前听说有时优化器可以优化标准的顺序。

所以我问:

  • 即使优化器选择了不同的路由,还有什么比检查 if 更快=null?我的意思是,我认为检查if a==null比正在运行的其他长的查询速度更快...

  • 如何强制SQL Server 按照我编写的方式运行查询(相同的顺序)?

RBa*_*ung 23

您陷入了“ Catch-All Query ”陷阱,Gail Shaw 在这里对此进行了很好的解释。

总结一下问题:SQL Server 通过在编译后缓存查询计划,然后在稍后编译之前检查匹配查询计划的缓存来优化查询编译的显着开销。这里发生的“匹配”是纯文本的,因此变量的实际值不会影响到这一点。

这在99% 的情况下都很好,但在某些情况下很糟糕。一种不好的情况是,当有人试图构造一个 WHERE 子句时,就好像它就像 C 中的一个短路 IF 语句一样。这不能很好地工作,因为 SQL 编译器必须制定一个无论如何都可以工作的查询计划参数值实际是什么,以及它可以处理 WHERE 子句中这些“聪明”逻辑切换条件的唯一方法是制定一个简单的蛮力计划,该计划仅扫描整个表,并在行进时过滤行, 不利用任何索引。

不出所料,无论参数/变量值是什么,这都会使它们始终变慢。


小智 8

没有保证的方法可以强制 SQL Server 以特定顺序执行您的子句条件。优化器将始终按照它认为合适的顺序评估它们。

你可以做的是这样的:

IF @LinkMode IS NULL
BEGIN
    select ...
    from ...
    WHERE (myColumn IN (...very long time exeted query...))
         ...
         ...
END
ELSE
BEGIN
    select ...
    from ...
    WHERE ...
         ...
END
Run Code Online (Sandbox Code Playgroud)