1.  现象

表结构如下

CREATE TABLE `ACT_HI_INST` (
`ID` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '主键',
`INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '流程实例id',
`BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT '' COMMENT '流程编号',
`CREATE_TIME_` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UPDATE_TIME_` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`ID`),
UNIQUE KEY `UIDX_INST` (`INST_ID_`),
UNIQUE KEY `UIDX_BKEY` (`BUSINESS_KEY_`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
执行下面语句, 发现没有走索引
explain
SELECT
*
FROM ACT_HI_INST hi
ORDER BY hi.BUSINESS_KEY_ DESC;

select count(*) from ACT_HI_INST ;
--

同时我们发现rows与实际表的数量存在差异,使用下面语句重新统计索引信息, 更正统计信息, 更新之后发现 rows 就数据表的数量基本一致(不完全一样是因为rows是采样统计而来的)。

analyze table ACT_HI_INST;

也就是说对于下面这条语句,尽管BUSINESS_KEY_  上有索引,MySQL还是选择了全表扫描。为什么会这样呢?

SELECT * FROM ACT_HI_INST hi ORDER BY hi.BUSINESS_KEY_ DESC;

2. 猜想

我猜想原因是 因为MySQL认为即使 使用 BUSINESS_KEY_  索引树进行查询,不需要排序,但是最后仍然需要回表,回表的次数 == 表的大小,这种代价比全表扫描然后排序的代价更大。

3. 验证

为了验证我的猜想,我加上在SQL语句最后加上 LIMIT 10 。如下所示

explain
SELECT
*
FROM ACT_HI_INST hi
ORDER BY hi.BUSINESS_KEY_ DESC limit 10;

果然我们看到加上 LIMIT 的语句走了索引。因为这个时候MySQL认为回表的代价比排序的代价更小,所以这个时候选择了走 BUSINESS_KEY_  索引。

除了上面这种方式可以验证我的猜想,还有一种方式,如下所示。我们只查询BUSINESS_KEY_ 。

因为此时叶子节点就包含我们需要查询的字段,这个时候不需要再回表,所以MySQL选择BUSINESS_KEY_  代价最小。

explain
SELECT
hi.BUSINESS_KEY_
FROM ACT_HI_INST hi
ORDER BY hi.BUSINESS_KEY_ DESC ;

4. 补充

这部分主要来源于极客时间林晓斌老师的《MySQL实战45讲》第16讲

order by a

如果 a 字段上有索引,MySQL innodb引擎是按照上诉的方式进行选择。如果a字段上没有索引,MySQL  innodb引擎 就会有两种排序方式:

全字段排序 和 rowid 排序。

全字段排序:将所有要选择的字段加入到sort_buffer中,然后在内存或者外部进行排序。如果能在内存中进行排序就在内存中进行排序。

如果要排序的数据量小于 sort_buffer_size,排序就在内存中完成。但如果排序数据量太大,内存放不下,则不得不利用磁盘临时文件辅助排序。

如果查询要返回的字段很多的话,那么 sort_buffer 里面要放的字段数太多,这样内存里能够同时放下的行数很少,要分成很多个临时文件,排序的性能会很差。这个时候MySQL就会采用rowId排序。

rowid排序:MySQL取出需要排序的字段和ID放入sort_buffer中进行排序,最后按照排序的结果,通过ID回表,返回数据到客户端。

MySQL 的一个设计思想是如果内存够,就要多利用内存,尽量减少磁盘访问。所以对应sort_buffer足够大的情况,MySQL会优选选择全字段排序。

【开发总结】order by 为什么没有走索引?的更多相关文章

  1. sql查询未走索引问题分析之查询数据量过大

    前因: 客户咨询,有一个业务sql(代表经常被执行且重要),全表扫描在系统占用资源很高(通过ash报告查询得到信息) 思路: 1.找到sql_text,sql_id 2.查看执行计划 3.查询sql涉 ...

  2. mysql 索引 create_time 加explain关键字是否走索引

    SELECT * FROM t_user WHERE email='217@xxg.com';  --1.725 --加email索引之后 0.003 SELECT * FROM t_user WHE ...

  3. Oracle中查询走索引的情况

    1.对返回的行无任何限定条件,即没有where子句 2.未对数据表与任何索引主列相对应的行限定条件例如:在City-State-Zip列创建了三列复合索引,那么仅对State列限定条件不能使用这个索引 ...

  4. varchar int 查询 到底什么情况下走索引?

    一个字符类型的.一个int类型的,查询的时候到底会不会走索引,其实很多工作了几年的开发人员有时也会晕,下面就用具体事例来测试一下. 1.  准备工作 先准备2张表,以备后续测试使用. 表1:创建表te ...

  5. 如何根据执行计划,判断Mysql语句是否走索引

    如何根据执行计划,判断Mysql语句是否走索引

  6. 以通配符(%)开始的like字符串,走索引

    在对oracle的SQL优化过程中经常会遇到[like'%abc']破坏索引的问题,但是如果真有此类需求,该如何在不破坏索引的基础上进行查询呢. [sql] view plain copy sys@m ...

  7. mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?

    情况描述:在MySQL的user表中,对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引? 根据查询字段的位置不同来决定,如查询a,     a,b    a,b, ...

  8. MySQL实现强制查询走索引和强制查询不缓存

    0.表结构如下:(包含两个索引) Create Table: CREATE TABLE `user` ( `userID` ) NOT NULL, `userCode` ) DEFAULT NULL, ...

  9. 强制MySQL查询走索引和强制查询不缓存

    有些情况下,表中创建了索引但是EXPLAIN的查看执行计划的时候发现并没有走索引.是因为优化器认为该语句不使用索引效率更好. 当然也可以强制走索引.类似: SELECT uid,uname FROM ...

随机推荐

  1. 分享一个bootstrap的上一步,下一步的插件

    效果图: 下载链接: https://www.daimabiji.com/index.php?m=content&c=down&a_k=ae0fI1gZyLT7oao56Pgu-dye ...

  2. Java之Annotation(注解)——注解处理器

    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...

  3. Linux系统修改服务器系统时间

    修改Linux系统时间,需要执行两个命令,如下: 第一条指令:date –s '2017-07-12 10:22:30' 第二条指令:clock –w //将日期写入CMOS

  4. Chrome中实时查看.md文件

    经常用Vim的朋友,在Vim中有一个Markdown语法高亮的插件,叫做:vim-markdown ,用起来还不错. 在Chrome中有一个实时预览Markdown效果的扩展,叫做:Markdown ...

  5. 经典游戏--24点--c++代码实现和总体思路(简单暴力向)

    24点 24点是一个非常经典的游戏,从扑克牌里抽4张牌,其中J=11,Q=12,K=13,然后经过+,-,*,/,(),的计算后,使得计算得值为24,例如抽到1,2,2,5四张牌,那么 (1+5)*( ...

  6. Python输入input、输出print

    1.输入input input是用于输入数据给变量.通过键盘输入的是字符串,如果需要其他格式,需要做转换.比如int.float类型数据,int() 如下是一个例子: 如果a不进行int转换,那么输入 ...

  7. java面试题0001-区分类中重载方法的依据是什么?

    到底是根据什么来区分类中重载的方法? A:不同的返回值类型. B:不同的参数类型. C:不同的访问权限. D:不同的参数名称. 解析: Step1.我们先在DifferentiateReload类中创 ...

  8. soso官方:网页分类技术介绍

    http://www.wocaoseo.com/thread-190-1-1.html 1.    技术背景     分类问题是人类所面临的一个非常重要且具有普遍意义的问题.将事物正确的分类,有助于人 ...

  9. 让“不确定性”变得有“弹性”?基于弹性容器的AI评测实践

    0. 前言 AI的场景丰富多彩,AI的评价方法百花齐放,这对于设计一套更通用的评测框架来说,是一个极大的挑战,需要兼顾不同的协议,不同的模型环境,甚至是不同的操作系统.本文分享了我们在AI评测路上的一 ...

  10. oracle读取ip_num用uint32_t接收,出错及解决

    start_ip_num = rset->getNumber(1); end_ip_num = rset->getNumber(2);2988 info_log("GetIpLi ...