点击蓝色“有关SQL”关注我哟

加个“星标”,天天与8000人一起快乐成长

在群里看到一个基础题,有关索引的使用。


题目就在这里,有的朋友说选B,有的选C,有的说题目不严谨,还有的说没答案,都是错误的。

讨论了很久,有两个共性的问题,值得拿出来说下:

  • a=1 and b=1 和 b=1 and a=1 会有效利用 idx(b,a) 吗?

  • b=1 还会利用索引 idx(a,b)吗?

实践出真知,我就试着上机操作下。

create database factory ;use factory
go create table dbo.workflow ( flowid int, flowamount int, flowcount int )go

先回答第一个问题,判断条件的顺序会影响索引使用吗

这儿模拟题目中的 idx(b,a) 索引结构create index idx_amt_id on dbo.workflow(flowamount,flowid)模拟 a=1 and b=1 的查询select * from dbo.workflow
where flowid = 1 and flowamount = 1 模拟 b=1 and a=1 的查询select * from dbo.workflow
where flowamount = 1 and flowid = 1

可以看到,当表新建,还没有数据时,优化器根本不会去判断用不用索引,而是直接全表扫描。反正就一个数据页。


当我们加点数据时,再看看反应:

这里不得不再提下 tally table 的用法,实在看不下去利用循环来生成测试数据的方法

DECLARE @BEGIN DATETIME = '2010-01-01',@END DATETIME = '2017-10-30'DECLARE @INC INT ;SELECT @INC = DATEDIFF(DAY,@BEGIN,@END); WITH L0 AS ( SELECT * FROM (VALUES(1),(2),(3)) AS T(C) ),    L1 AS (SELECT a.C,b.C AS BC FROM L0 AS a cross join L0 AS b ),    L2 AS (SELECT a.C,b.C AS BC FROM L1 AS a cross join L1 AS b ),    L3 AS (SELECT a.C,b.C AS BC FROM L2 AS a cross join L2 AS b ),    L4 AS (SELECT a.C,b.C AS BC FROM L3 AS a cross join L3 AS b ),    L5 AS (SELECT a.C,b.C AS BC FROM L4 AS a cross join L4 AS b )insert into  dbo.workflow (flowid,flowamount,flowcount)            SELECT TOP 50000 RNK , RNK * 10, RNK + 20 FROM (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RNK FROM L5) M

此时表里有5万条数据,再看上面两条查询的执行计划:

这儿模拟题目中的 idx(b,a) 索引结构create index idx_amt_id on dbo.workflow(flowamount,flowid)模拟 a=1 and b=1 的查询select * from dbo.workflow
where flowid = 1 and flowamount = 1 模拟 b=1 and a=1 的查询select * from dbo.workflow
where flowamount = 1 and flowid = 1


很明显,都会走索引 idx(b,a) 这种模式,与 b 在前和 a 在前无关。优化器可以优化这部分表达式的重组。

但,是不是所有条件表达式都没有先后顺序要求呢?肯定不是

只有在相等条件判断时,先后顺序不重要,一旦有表达式用于非等判断,顺序就很重要了,如下:

select * from dbo.workflow
where flowamount > 39 and flowid = 1 select * from dbo.workflow
where flowid = 1 and flowamount > 39


这里优化器提示(绿色字体部分),建立一个相等判断条件的索引在前,非等判断字段在后的索引 (flowid,flowamount)。所以本质上,索引结构中字段先后不受制于查询中相等判断条件表达式字段的顺序,而受制于非等条件判断表达式。即非等判断字段(flowamount>39)需要放在相等判断字段(flowid=1)的后面。

create index idx_id_amtr on dbo.workflow(flowid,flowamount)select * from dbo.workflow
where flowamount > 39 and flowid = 1 select * from dbo.workflow
where flowid = 1 and flowamount > 39

再看两者的执行计划:


这里就走了我们刚才新建的索引 idx_id_amtr

第二个问题,b=1 还会利用索引 idx(a,b)吗

在上面的示例中,建立 index(flowamount,flowid) 的索引,那么对应到要解决的问题,便是 where flowid = 1 会走 index(flowamount,flowid)的索引吗?

select * from dbo.workflow
where  flowid = 1


由此可见 b=1 是不会利用索引 idx(a,b) 了。

注意,或许 oracle, mysql, pg, 等其他数据库会有不同,大家可以尝试实际操作下,再一起来讨论。各自优化器的算法不同,优化略微有些诧异。不必过于纠结。

--完--

往期精彩:

本号精华合集(二)

如何写好 5000 行的 SQL 代码

如何提高阅读 SQL 源代码的快感

我在面试数据库工程师候选人时,常问的一些题

零基础 SQL 数据库小白,从入门到精通的学习路线与书单

SQL 中判断条件的先后顺序,会引起索引失效么?相关推荐

  1. mysql 查询后根据值的不同进行判断与修改,SQL中的条件判断语句(case when zhen)用法

    需求: mysql 查询后根据值的不同进行判断与修改 语法结构: SQL中的条件判断语句(case when zhen)用法 SELECT A.品号,属性,        CASE           ...

  2. SQL中on条件与where条件的区别

    SQL中on条件与where条件的区别 数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: ...

  3. pandas使用query函数基于判断条件获得dataframe中满足条件的数据行(row)的索引列表(index of rows matching conditions in dataframe)

    pandas使用query函数基于判断条件获得dataframe中满足条件的数据行(row)的索引列表(index of rows matching conditions in dataframe) ...

  4. SQL中过滤条件放在on和where中的区别

    sql中过滤条件放在on和where中的区别,inner join没区别.后来才想起来,连接查询除了inner join还有right join,left join. join过程可以这样理解:首先两 ...

  5. MySQL查询时条件的顺序_mysql中查询条件的先后顺序问题?

    听一个讲座,说查询条件的顺序影响查询速度,比如一个先运行一个高门槛的条件,后低门槛,运行速度会相对快,请问有这种事么? 那么我在写thinkphp的查询语句的时候,是不是应该把高门槛的放在前面查询? ...

  6. Oracle数据库第四课——PL/SQL中的条件控制

    知识点: PL/SQL 有 3 种类型的条件控制结构:IF.ELSIF 和 CASE 语句.掌握 IF 语句的用法, 掌握 ELSIF 语句的用法, 理解嵌套 IF 语句的用法, 掌握 CASE 语句 ...

  7. Mysql查询条件为大于时,不走索引失效问题排查

    我们都知道在数据库查询时,索引可以极大的提高查询效率.通常在使用的时候,都会针对频繁查询的关键字段建立索引. 比如,当以交易日期(trans_date)来查询交易记录时,通常会对该字段添加索引,以便在 ...

  8. for(;;)函数中判断条件执行顺序

    for(i=100;i>=0:--i) { cout<<"i="<<i<<endl; } 它的执行过程如下: 1)        先求解表 ...

  9. SQL中的条件判断语句(case when zhen)用法

    简介: case具有两种格式.简单case函数和case搜索函数.这两种方式,可以实现相同的功能.简单case函数的写法相对比较简洁,但是和case搜索函数相比,功能方面会有些限制,比如写判定式.还有 ...

最新文章

  1. gdoi2017总结
  2. R语言dplyr包获取dataframe分组聚合汇总统计值实战(group_by() and summarize() ):均值、中位数、分位数、IQR、MAD、count、unique
  3. 设置UITableView设置contentsize
  4. 选择排序 冒泡排序 二分查找
  5. Linux手机适配,nginx同时适配PC版和手机移动版
  6. Android 获取app 地址,获取手机设备信息、app版本信息、ip地址
  7. 【CCF】201712-2游戏
  8. 关于onSaveInstanceState的javadoc的渣渣翻译
  9. 不确定性原理的前世今生 · 数学篇(一)
  10. 学习c语言编程用什么软件_用C编程
  11. 浩方对战平台原理初步分析
  12. Autumn中文文档3:接收客户端数据
  13. 考研政治80+经验:政治86分教你怎么复习
  14. 信息安全专业要计算机好吗,哪些单位需要计算机信息安全专业的
  15. 【DL】长短期记忆网络(LSTM)
  16. IntelliJ IDEA旗舰版 下载安装
  17. eclipse介绍,环境配置,mysql安装
  18. mp4格式转换专家-魔法mp4格式转换器轻松应对mp4电影格式转换
  19. c语言定义一个结构体描述学生信息,1)定义一个结构体描述学生信息(学号,姓名,性别,年龄,住址); 2)设计一个函数,用于显示单个学生信息,函...
  20. Android Studio 蓝牙通信BlueTooth

热门文章

  1. 2.格式化输出与输入
  2. 如何统计项目的代码行数
  3. 原生JS实现拿到的时间戳“毫秒/秒”转为“时:分:秒”形式的效果
  4. 【惊了】迅雷下载速度竟然比不上虚拟机中的下载速度
  5. 【建议收藏】一份网络安全面试宝典请查收!!
  6. 如何导入后缀ndm的文件
  7. Python GPU加速
  8. js 排班插件_排班小程序
  9. 在visio里面插入带圆圈的数字字符。
  10. vanilla_包装Vanilla JavaScript软件包以在React中使用