强制SQL Server按照编写的条件运行查询条件?


14

我正在使用SQL Server 2008 R2,并且具有以下伪查询(SP):

select ...
from ...
WHERE    @LinkMode IS NULL
     AND (myColumn IN (...very long-running query...))
     ...
     ...

问题是查询要花很长时间才能执行-即使我使用来执行SP @LinkMode=2

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

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

 select ...
    from ...
    WHERE    1=2
         AND (myColumn IN (...very long time exeted query...))
     ...
     ...

SP 确实运行很快。

我之前听说过,有时优化器可以优化条件的顺序。

所以我问:

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

  • 如何强制 SQL Server在编写查询时(相同顺序)运行查询?

Answers:


22

您将陷入“ 全部捕获查询 ”陷阱,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

3

如果这是一个选项,请使用IF语句执行适当形式的查询。另外,在SQL中,您告诉数据库引擎该做什么,而不是该怎么做-事情没有从头到尾执行。很难预测将要执行的操作。您也许知道这一点;)


2

动态SQL可能也可以工作,因为在这种情况下,查询优化器应该在运行时获取实际值(如果我错了,请更正我,我不确定,但似乎记得在类似情况下使用它)。但是,我与其他人一样,因为IF / ELSE子句将为您提供最佳服务,因为它是最简单,最简单的解决方案,可以满足所需的一切。

如果您还没有使用它,以供将来参考,那么可以在这里找到一个非常丑陋的站点,其中提供了有关动态SQL的有效示例,例如:http : //sqlusa.com/bestpractices/dynamicsql/


1

我建议使用IF / ELSE构造。如果由于某种原因对您不起作用,则始终可以考虑使用WITH RECOMPILE选项。


您能否详细说明“ if / else构造”的外观?:D
jcolebrand

我打算建议使用OPTION(WITH RECOMPILE),因为那样每次都会生成一个理想的计划-编译延迟会增加开销,但是我怀疑在这种情况下总体上会更好。
SqlRyan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.