文档章节

SQL Server的WHERE条件"短路评价"大杀器CASE WHEN

Q_J
 Q_J
发布于 2016/06/09 22:29
字数 807
阅读 93
收藏 7

可惜证据文档取不出来,而且冗长,就大致做个备忘录,有心的人看看就明白了。


1. 条件里没有子查询 -> 短路评价

SELECT * FROM test WHERE some_fast_check()=1 OR some_slow_check(c) = 1

2. 条件里有子查询,但子查询是针对真实表的 -> 准“短路评价”

SELECT * FROM test WHERE some_fast_check()=1 OR c IN (SELECT * FROM normal_or_temp_table)

需要注意的是:子查询一定会最先执行,相当于先做成一个内存表,勉强说得过去,但是万一这个子查询很慢,偏偏第一个条件已经满足了的时候,那就悲剧了,拖累了整个速度

的确,如果第一个条件满足的话,这之后对于形成的内存表进行Scan的次数=0,所以说这是准 “短路评价”。


3. 条件里有子查询,且使用了“表函数” -> 开始失去控制了。

SELECT * FROM test WHERE some_fast_check()=1 OR c IN (SELECT * FROM some_slow_data())

尤其是上述例子里“标量函数”和“表函数”混合的,是最超乎想象的,这时,

some_slow_data()表函数一定最先被执行一次以便其产生内存表,这个只好忍了。

但是这之后就不可忍了!对于这个内存表,总会被进行N次Scan,而N显然取决于主表里符合其他条件的件数。

就是说就算所有行的some_fast_check()=1已经为true了,这后面针对内存表的Scan还是继续做!

傻啊。没办法,从Plan看就是这样的,SQL Server就是这么任性。

当然,结果速度快不快,还要取决于优化器否决定并发执行,有时也不慢。


4. 短路评价大杀器"CASE WHEN"

例如把下面这句整体当做一个表达式来评价时,当"快速条件"满足了时,整个表达式就出结果(1)了,"慢速条件"都不会被执行,

CASE WHEN 快速条件 THEN 1 WHEN 慢速条件 THEN 1 ELSE 0 END

于是,整个SQL改成:

SELECT * FROM test WHERE 
    CASE WHEN some_fast_check()=1 THEN 1
         WHEN c IN (SELECT * FROM some_slow_data()) THEN 1
         ELSE 0
    END = 1

就可以变快了。


 

还有,不知道DB为什么没有默认开启RECOMPILE选项,这个选项会减少哪些不必要的子查询。

测试时,必须注意用dbcc命令清楚缓存,具体的命令一查就行。

另外一个确定的经验是,IN换成EXISTS或者TABLE JOIN的方式在第一次执行时(没有缓存),Plan是一样的,后来有了Cache之后,TABLE JOIN方式就快些。

© 著作权归作者所有

共有 人打赏支持
Q_J

Q_J

粉丝 12
博文 67
码字总数 54682
作品 0
日本
私信 提问
《SQLSERVER2012之T-SQL教程》T-SQL单表查询(二)

表结构与数据:https://github.com/XuePeng87/TSQLV4 谓词和运算符 1) 谓词 T-SQL支持的谓词例子包括IN、BETWEEN和LIKE。 IN可以检查一个值或是一个标量表达式是否至少等于集合中的一个元素。...

杰克鹏仔
2016/11/09
8
0
2.《SQLSERVER2012之T-SQL教程》T-SQL单表查询(二)

表结构与数据:https://github.com/XuePeng87/TSQLV4 谓词和运算符 1) 谓词 T-SQL支持的谓词例子包括IN、BETWEEN和LIKE。 IN可以检查一个值或是一个标量表达式是否至少等于集合中的一个元素。...

巧乐兹
2016/10/25
2
0
T-SQL基础(一)之简单查询

名词解释 SQL: Structured Query Language,结构化查询语言,是一种在关系型数据库中用于管理数据的标准语言。SQL是一种声明式编程语言,即只需表明需要什么而无需关注实现细节(C#中的LINQ也...

雪飞鸿
11/02
0
0
Oracle短路 “filter(NULL IS NOT NULL)”

CopyFrom: http://www.cnblogs.com/fangwenyu/p/3305394.html 了不起的 “filter(NULL IS NOT NULL)” 经常会在执行计划中看到很奇怪的"FILTER"操作,然后看对应的执行信息是"filter(NULL IS...

yqh_2000
2015/01/30
0
0
【黑魔法】Covering Indexes、STRAIGHT_JOIN

今天给大家介绍两个黑魔法,这都是压箱底的法宝。大家在使用时,一定要弄清他们的适用场景及用法,用好了,就是一把开天斧,用不好那就是画蛇添足。自从看过耗子哥(左耳朵耗子)的博客,都会...

夏雪冬日
08/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

EOS官方钱包keosd

EOS官方钱包的名称是keosd,它负责管理你的私钥,并且帮你进行交易的签名。 不过不幸的是,keosd钱包对普通用户并不友好,它是一个命令行程序,目前还没有像以太坊的mist那样的图形化界面,而...

汇智网教程
今天
25
0
ArrayList的实现原理以及实现线程安全

一、ArrayList概述 ArrayList是基于数组实现的,是一个动态的数字,可以自动扩容。 ArrayList不是线程安全的,效率比较高,只能用于单线程的环境中,在多线程环境中可以使用Collections.syn...

一看就喷亏的小猿
今天
31
0
Netty 备录 (一)

入职新公司不久,修修补补1个月的bug,来了点实战性的技术---基于netty即时通信 还好之前对socket有所使用及了解,入手netty应该不是很难吧,好吧,的确有点难,刚看这玩意的时候,可能都不知道哪里...

_大侠__
昨天
35
0
Django简单介绍和用户访问流程

Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。 Django是一个开放源代码的Web应用框架,由Python写成。 Django遵守BSD版权,初...

枫叶云
昨天
48
0
Spring Cloud Stream消费失败后的处理策略(四):重新入队(RabbitMQ)

应用场景 之前我们已经通过《Spring Cloud Stream消费失败后的处理策略(一):自动重试》一文介绍了Spring Cloud Stream默认的消息重试功能。本文将介绍RabbitMQ的binder提供的另外一种重试...

程序猿DD
昨天
24
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部