MySQL优化:回表

走出舒适圈,你会成为最好的自己


前言

今天被问到了回表,不知道这个是什么鬼,回来一查原来是这个啊,记录一下……
要了解这个需要先知道聚集索引、普通索引、联合索引


一、聚集索引是什么?

1.聚集索引(clustered index)

示例表:

create table user (
    id int primary key,
    name varchar(20),
    sex varchar(5),
    index(name)
)engine=innodb;

InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:

  1. 如果表定义了PK,则PK就是聚集索引
  2. 如果表没有定义PK,则第一个out null unique列是聚集索引
  3. 否则,InnoDB会创建一个隐藏的row-id作为聚集索引

备注:所以PK查询非常快,直接定位行记录

InnoDB普通索引的叶子节点存储主键值。
备注:注意,不是存储行记录头指针,MyISAM的索引叶子节点存储记录指针。

2.聚集索引与普通索引区别(非聚集索引)

示例数据:

INSERT INTO user (id, name, sex) VALUES (1, 'shenjian', 'm');
INSERT INTO user (id, name, sex) VALUES (3, 'zhangsan', 'm');
INSERT INTO user (id, name, sex) VALUES (5, 'lisi', 'm');
INSERT INTO user (id, name, sex) VALUES (9, 'wangwu', 'f');

存储数据的区别
在这里插入图片描述
两个B+树索引存储分别如上图所示:

  1. id为PK,聚集索引,叶子节点存储行记录
  2. name为key,普通索引,叶子节点存储PK值,即id
    备注:所以通过name查询所有字段时需要扫描两遍索引树。

如:

select * from t where name='lisi'; 

执行过程,如下:
在这里插入图片描述
如:粉红色路径,需要扫描两遍索引树:

  1. 先通过普通索引(非聚集索引)定位到主键值id=5
  2. 再通过聚集索引定位到行记录

注:这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。

3. 如何实现索引覆盖

常用方法是:将被查询的字段,建立到联合索引里去。

使用user表:

  1. 能够命中name索引,索引叶子节点存储了主键id,通过name的索引树即可获取id和name,无需回表,符合索引覆盖,效率较高。
select id,name from user where name='shenjian'; 

在这里插入图片描述
2. 能够命中name索引,索引叶子节点存储了主键id,但sex字段必须回表查询才能获取到,不符合索引覆盖,需要再次通过id值扫码聚集索引获取sex字段,效率会降低。

select id,name,sex from user where name='shenjian';

在这里插入图片描述
优化:把name单列索引升级为联合索引(name,sex)效果就不同了

create table user (
    id int primary key,
    name varchar(20),
    sex varchar(5),
    index(name, sex)
)engine=innodb;

select id,name ... where name='shenjian';
select id,name,sex ... where name='shenjian';

以上两个都能命中索引覆盖,无需回表。

4. 那些场景可以优化

4.1 全表count查询优化

在这里插入图片描述
原表为:
user(PK id, name, sex);
直接:不能利用索引覆盖。

select count(name) from user;

添加索引:就能够利用索引覆盖提效。

alter table user add key(name);

4.2 列查询回表优化

select id,name,sex ... where name='shenjian';

就能够利用索引覆盖提效。

4.3 分页查询

select id,name,sex ... order by name limit 500,100;

将单列索引(name)升级为联合索引(name, sex),也可以避免回表。

总结

有些东西,还在需要整理记忆的

参考文档:
MySQL优化:如何避免回表查询?什么是索引覆盖? (转)

猜你喜欢

转载自blog.csdn.net/bj_ameng/article/details/115212123