首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过添加未使用的WHERE条件使查询运行更长时间

通过添加未使用的WHERE条件使查询运行更长时间
EN

Stack Overflow用户
提问于 2009-11-11 00:40:24
回答 2查看 374关注 0票数 1

我遇到了一个有趣的问题(至少对我来说很有趣)。下面是我的查询的大体概念。假设@AuthorType是存储过程的输入,并且在我放置注释的每个位置都有各种特定的条件。

代码语言:javascript
复制
SELECT *
FROM TBooks
WHERE
(--...SOME CONDITIONS)
OR
(@AuthorType = 1 AND --...DIFFERENT CONDITIONS)
OR
(@AuthorType = 2 AND --...STILL MORE CONDITIONS)

我感兴趣的是,如果我在@AuthorType = 0的情况下执行这个SP,它的运行速度会比删除最后两组条件(为@AuthorType的特殊值添加条件的那两组)要慢。

SQL Server不应该在运行时意识到这些条件永远不会得到满足并完全忽略它们吗?我遇到的差异并不小;它大约使查询的长度增加了一倍(1-2秒到3-5秒)。

我是否期望SQL Server对此进行过多优化?对于特殊情况,我真的需要有3个单独的SP吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-11 01:27:23

难道SQL Server不应该在运行时意识到这些条件永远不会得到满足并完全忽略它们吗?

不,绝对不是。这里有两个因素在起作用。

  1. SQL Server not保证布尔运算符短路。有关清楚地展示查询优化如何颠倒布尔表达式求值顺序的示例,请参阅On SQL Server boolean operator short-circuit。乍一看,这似乎是命令式C编程思维模式的一个错误,但对于面向声明集的SQL世界来说,这是正确的做法。
  2. OR是SQL SARGability的敌人。将SQL语句编译成执行计划,然后执行该计划。计划在两次调用之间得到重用(被缓存)。因此,SQL编译器必须生成一个适合所有独立OR情况(@AuthorType=1和@AuthorType=2以及@AuthorType=3)的计划。当涉及到生成查询计划时,在某种意义上,就好像@AuthorType会同时拥有所有的值一样。结果几乎总是最糟糕的计划,该计划无法使任何索引受益,因为不同的OR分支相互冲突,因此它最终扫描整个表并逐个检查行。

在您的情况下,以及任何其他涉及布尔OR的情况下,最好的做法是将@AuthorType移出查询:

代码语言:javascript
复制
IF (@AuthorType = 1)
  SELECT ... FROM ... WHERE ...
ELSE IF (@AuthorType = 2)
  SELECT ... FROM ... WHERE ...
ELSE ...

因为每个分支都清楚地划分到各自的语句中,所以SQL可以为每个单独的情况创建适当的访问路径。

下一个最好的方法是使用UNION ALL,这是chadhoc已经建议的方式,并且是视图或其他需要单个语句的地方的正确方法(允许使用no IF )。

票数 6
EN

Stack Overflow用户

发布于 2009-11-11 00:54:50

这是由于优化器很难处理"OR“类型的逻辑以及issuesparameter sniffing所做的事情。尝试将上面的查询更改为UNION方法,如文章here中所述。也就是说,你最终会得到多个联合在一起的语句,只有一个@AuthorType =x和,允许优化器排除AND逻辑与给定的@AuthorType不匹配的部分,并依次查找适当的索引...看起来像这样:

代码语言:javascript
复制
SELECT *
FROM TBooks
WHERE
(--...SOME CONDITIONS)
AND @AuthorType = 1 AND --...DIFFERENT CONDITIONS)
union all
SELECT *
FROM TBooks
WHERE
(--...SOME CONDITIONS)
AND @AuthorType = 2 AND --...DIFFERENT CONDITIONS)
union all
...
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1709348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档