本文转载自微信公众号「飞天小牛肉」,排上作者小牛肉。覆盖转载本文请联系飞天小牛肉公众号。索引
小伙伴们可以先看这篇文章了解下什么是聚集索引和辅助索引:Are You OK?主键、聚集索引、询快辅助索引,排上简单回顾下,覆盖聚集索引的索引叶子节点包含完整的行数据,而非聚集索引的表查叶子节点存储的是每行数据的辅助索引键 + 该行数据对应的聚集索引键(主键值)。
假设有张 user 表,询快包含 id(主键),排上name,覆盖age(普通索引)三列,索引有如下数据:
- id name age
- 1 Jack 18
- 7 Alice 28
- 10 Bob 38
- 20 Carry 48
画一个比较简单比较容易懂的图来看下聚集索引和辅助索引:
如果查询条件为主键,则只需扫描一次聚集索引的 B+ 树即可定位到要查找的行记录。举个例子:
- select * from user where id = 7;
查找过程如图中绿色所示:
如果查询条件为普通索引(辅助索引) age,则需要先查一遍辅助索引 B+ 树,根据辅助索引键得到对应的聚集索引键,然后再去聚集索引 B+ 树中查找到对应的行记录。举个例子:
- select * from user where age = 28;
上述 select * 等同于 select id, age, name 对吧,id 是主键索引,age 是普通索引,而 name 并不存在于 age 索引的 B+ 树上,所以通过 age 索引查询到 id 和 age 的值之后,还需要去聚集索引上才能查到 name 的值。
如图所示,第一步,查 age 辅助索引:
第二步,查聚集索引:
这就是所谓的回表查询,因为需要扫描两次索引 B+ 树,所以很显然它的性能较扫一遍索引树更低。
覆盖索引的目的就是避免发生回表查询,也就是说,通过覆盖索引,只需要扫描一次 B+ 树即可获得所需的行记录。
上文解释过,下面这个 SQL 语句需要查询两次 B+ 树:
- select * from user where age = 28;
我们将其稍作修改,使其只需要查询一次 B+ 树:
- select id, age from user where age = 28;
之前我们的返回结果是整个行记录,现在我们的返回结果只需要 id 和 age。
id 是什么?主键索引(聚集索引),age 是什么?普通索引(辅助索引),age 索引的 B+ 树的叶子节点存储的是什么?辅助索引键 + 对应的聚集索引键
所以这条 SQL 语句只需要扫描一次 age 索引的 B+ 树就行了
这样,结合这个例子,不知道各位有没有受到启发,如何实现覆盖索引拒绝回表查询呢?
答:联合索引。
我们把 age,name 设置为联合索引:
- create index idx_age_name on user(`age`,`name`);
此时 age 和 name 作为辅助索引键都在同一棵辅助索引的 B+ 树上,所以只需扫描一次这个组合索引的 B+ 树即可获取到 id、age 和 name,这就是实现了索引覆盖
在下面三个场景中,可以使用覆盖索引来进行优化 SQL 语句:
1)列查询回表优化(如上面讲的例子,将单列索引 age 升级为联合索引(age, name))
2)全表 count 查询
举个例子,假设 user 表中现在只有一个索引即主键 id:
- select count(age) from user;
可以用 explain 分析下这条语句,如果 Extra 字段为 Using index 时,就表示触发索引覆盖:
显然现在是没有触发覆盖索引的,我们来优化下:将 age 列设置为索引 create index idx_age on user(age),这样只需要查一遍 age 索引的 B+ 树即可得到结果:
3)分页查询
- select id, age, name from user order by username limit 500, 100;
对于这条 SQL,因为 name 字段不是索引,所以在分页查询需要进行回表查询。
Using filesort 表示没有使用索引的排序,或者说表示在索引之外,需要额外进行外部的排序动作。看到这个字段就应该意识到你需要对这条 SQL 进行优化了。
使用索引覆盖优化:将 (age, name) 设置为联合索引,这样只需要查一遍 (age, name) 联合索引的 B+ 树即可得到结果。
责任编辑:武晓燕 来源: 飞天小牛肉 SQL索引查询
(责任编辑:综合)
保利协鑫能源(3800.HK)盈警后低开高走半日收涨7% 多晶硅价格明显上升
沃尔核材(002130.SZ)公司高级管理人员马葵暂未减持股份 减持期过半
全国房地产开发投资增速连续7个月正增长 东部和西部区域的增长明显
大别山革命老区正式迎来“高铁时代” 黄黄高铁正线全长126.85公里
中炬高新(600872)融资融券信息 融券偿还量2,700股(10
全国房地产开发投资增速连续7个月正增长 东部和西部区域的增长明显
正业国际(03363.HK)全年纯利下降33.35% 每股基本盈利人民币11分
江苏省大运河文化带建设联席会议办公室召开大运河文化带建设规划会议