本文主要是介绍快速理解 Mysql 回表 索引覆盖 索引下推,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
快速理解 Mysql 回表 索引覆盖 索引下推
- 回表操作
- 索引覆盖
- 索引下推
回表操作
Mysql 每页大小为16K(B+树结构,所以16K足以),关于主键索引和辅助索引的结构这里简单说一下。
InnoDB 主键(聚簇索引):仅在叶子节点存储数据,且是整行数据
。
InnoDB 普通索引(辅助索引):仅在叶子节点存储对应的主键
。
比如:
有一张
account
表,其中id
为主键,name
为普通索引,age
无索引。
id | name | age |
---|---|---|
1 | 张一 | 90 |
2 | 张二 | 91 |
3 | 张三 | 92 |
4 | 李四 | 93 |
此时如果执行
select * from account where name = '张三';
# 下面这条语句和上面相同
select id,name,age from account where name = '张三';
虽然name
建立了索引,但是普通索引叶子节点仅存储该列对应的主键
,我们select *
包含了无索引的age
字段,所以需要①通过name索引找到主键
,②去主键索引的b+树中找整行记录
。
这个通过普通索引找对应主键,再去主键索引中寻找数据的过程,我们叫作
回表
。
索引覆盖
如果是这条语句就不会进行回表操作:
select id,name from account where name = '张三';
我们仅需要查询id
和name
,我们通过name
索引即可获取到主键,又因为name
我们直接使用的是=
查询(过滤出来的name
绝对就是张三,不可能是其他的),所以无需再进行回表操作,这就叫索引覆盖
。
那么考虑一下,下面这条语句会进行回表吗?
select id,name from account where name like '张%';
注意,我将=
换成了like
。
答案是会进行回表,因为有很多个张姓,like在右侧%虽然是会用到
name
索引,但通过name
索引我们仅能过滤出了所有张姓的人,此时通过叶子节点只能获取到对应主键,所以需要主键去回表得到具体的name
。
索引下推
假设
account
表数据表结构如下
id为主键索引,name和age为联合索引
id | name | age |
---|---|---|
1 | 张一 | 90 |
2 | 张二 | 91 |
3 | 张三 | 92 |
4 | 李四 | 93 |
select * from account where name like '张%' and age=90;
首先name
和age
是联合索引,且查询符合最左匹配原则
,会使用索引进行查询。
mysql 5.6之前
忽略掉age字段,仅通过name字段索引找到符合条件的数据(3个),然后进行回表操作,再去判断age是否符合.,由于找到3条符合条件的数据,所以需要3次回表操作。
mysql 5.6之后
不忽略age字段,在索引内部直接判断age是否同样符合条件,所以仅能找到1条符合条件的数据,因为我们用的是like,所以还是需要回表,但仅需要回表1次。
这篇关于快速理解 Mysql 回表 索引覆盖 索引下推的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!