【开发总结】order by 为什么没有走索引?
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 为什么没有走索引?的更多相关文章
- sql查询未走索引问题分析之查询数据量过大
前因: 客户咨询,有一个业务sql(代表经常被执行且重要),全表扫描在系统占用资源很高(通过ash报告查询得到信息) 思路: 1.找到sql_text,sql_id 2.查看执行计划 3.查询sql涉 ...
- mysql 索引 create_time 加explain关键字是否走索引
SELECT * FROM t_user WHERE email='217@xxg.com'; --1.725 --加email索引之后 0.003 SELECT * FROM t_user WHE ...
- Oracle中查询走索引的情况
1.对返回的行无任何限定条件,即没有where子句 2.未对数据表与任何索引主列相对应的行限定条件例如:在City-State-Zip列创建了三列复合索引,那么仅对State列限定条件不能使用这个索引 ...
- varchar int 查询 到底什么情况下走索引?
一个字符类型的.一个int类型的,查询的时候到底会不会走索引,其实很多工作了几年的开发人员有时也会晕,下面就用具体事例来测试一下. 1. 准备工作 先准备2张表,以备后续测试使用. 表1:创建表te ...
- 如何根据执行计划,判断Mysql语句是否走索引
如何根据执行计划,判断Mysql语句是否走索引
- 以通配符(%)开始的like字符串,走索引
在对oracle的SQL优化过程中经常会遇到[like'%abc']破坏索引的问题,但是如果真有此类需求,该如何在不破坏索引的基础上进行查询呢. [sql] view plain copy sys@m ...
- mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?
情况描述:在MySQL的user表中,对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引? 根据查询字段的位置不同来决定,如查询a, a,b a,b, ...
- MySQL实现强制查询走索引和强制查询不缓存
0.表结构如下:(包含两个索引) Create Table: CREATE TABLE `user` ( `userID` ) NOT NULL, `userCode` ) DEFAULT NULL, ...
- 强制MySQL查询走索引和强制查询不缓存
有些情况下,表中创建了索引但是EXPLAIN的查看执行计划的时候发现并没有走索引.是因为优化器认为该语句不使用索引效率更好. 当然也可以强制走索引.类似: SELECT uid,uname FROM ...
随机推荐
- 分享一个bootstrap的上一步,下一步的插件
效果图: 下载链接: https://www.daimabiji.com/index.php?m=content&c=down&a_k=ae0fI1gZyLT7oao56Pgu-dye ...
- Java之Annotation(注解)——注解处理器
如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...
- Linux系统修改服务器系统时间
修改Linux系统时间,需要执行两个命令,如下: 第一条指令:date –s '2017-07-12 10:22:30' 第二条指令:clock –w //将日期写入CMOS
- Chrome中实时查看.md文件
经常用Vim的朋友,在Vim中有一个Markdown语法高亮的插件,叫做:vim-markdown ,用起来还不错. 在Chrome中有一个实时预览Markdown效果的扩展,叫做:Markdown ...
- 经典游戏--24点--c++代码实现和总体思路(简单暴力向)
24点 24点是一个非常经典的游戏,从扑克牌里抽4张牌,其中J=11,Q=12,K=13,然后经过+,-,*,/,(),的计算后,使得计算得值为24,例如抽到1,2,2,5四张牌,那么 (1+5)*( ...
- Python输入input、输出print
1.输入input input是用于输入数据给变量.通过键盘输入的是字符串,如果需要其他格式,需要做转换.比如int.float类型数据,int() 如下是一个例子: 如果a不进行int转换,那么输入 ...
- java面试题0001-区分类中重载方法的依据是什么?
到底是根据什么来区分类中重载的方法? A:不同的返回值类型. B:不同的参数类型. C:不同的访问权限. D:不同的参数名称. 解析: Step1.我们先在DifferentiateReload类中创 ...
- soso官方:网页分类技术介绍
http://www.wocaoseo.com/thread-190-1-1.html 1. 技术背景 分类问题是人类所面临的一个非常重要且具有普遍意义的问题.将事物正确的分类,有助于人 ...
- 让“不确定性”变得有“弹性”?基于弹性容器的AI评测实践
0. 前言 AI的场景丰富多彩,AI的评价方法百花齐放,这对于设计一套更通用的评测框架来说,是一个极大的挑战,需要兼顾不同的协议,不同的模型环境,甚至是不同的操作系统.本文分享了我们在AI评测路上的一 ...
- oracle读取ip_num用uint32_t接收,出错及解决
start_ip_num = rset->getNumber(1); end_ip_num = rset->getNumber(2);2988 info_log("GetIpLi ...