好的索引当然是要覆盖了!

简介: 好的索引当然是要覆盖了!

如果你的查询中用到了索引,这是一个进步,如果能够更进一步,用到了覆盖索引,那么就更牛了!当我们设计一个索引的时候,如果能够从一个更加全面的角度去设计这个索引,不仅考虑到 where 中的条件,还能够考虑到整个 SQL,那么无疑这个索引的设计将是非常成功的。

当然不能为了覆盖而覆盖。

1. 什么是覆盖索引

要理解什么是覆盖索引,我们需要先来回顾一下 InnoDB 中索引树的数据结构。

假设我有如下数据:

id(主键) username age address gender
1 ab 99 深圳
2 bw 95 天津
3 cx 93 深圳
4 bc 80 上海
5 bg 85 重庆
6 ac 98 广州
7 bw 99 海口
8 ck 90 深圳
9 cc 92 武汉
10 af 88 北京

现在我给 username、age 以及 address 三个字段建立一个联合索引,那么这个联合索引的 B+Tree 可能是这个样子:

911fba580abf0e846a9022afbae858d3.png

上面这个索引树是一个非聚集索引或者也可以说是一个二级索引,这种索引区别于我们之前文章跟大家聊的聚集索引(再聊 MySQL 聚簇索引),在聚集索引中,叶子结点就是这一行的数据,但是在二级索引中,叶子结点中保存的是主键值。

所以,当我们搜索的时候,如果使用的是二级索引,那么最终拿到的是主键值,有了主键值之后,我们还需要再去到聚簇索引中进行搜索,才能拿到完整的数据,这个过程我们也称之为回表。

很明显,如果进行了回表操作的话,那么执行效率显然就要下降一截,那么是否用到了二级索引就会回表呢?其实不然!如果是覆盖索引的话,就不需要回表。

那么什么是覆盖索引呢?

小伙伴们观察上面的索引树,大家发现在这个索引树中,离叶子结点最近的树枝上有 username、age 以及 address,而叶子结点上有 id,所以如果我想要查询的字段是 id、username、age 以及 address 中的任意一个或者任意几个的话,那么就不需要再去聚簇索引上查询了,当前这个 B+Tree 上直接就有现成的,直接返回即可,这个就是覆盖索引。

2. 实践

现在假设我有如下一张表:

CREATE TABLE `user` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `gender` varchar(2) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_prop_index` (`username`,`age`,`address`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

可以看到,这张表中有一个名为 user_prop_index 的索引,这个索引中一共存在三个字段,分别是 username、age 以及 address,现在我们来看如下 SQL 的执行计划:

explain select address from user where username='ab' and age=99\G

bb3dd812bac29eb97773a206974700e6.png

小伙伴们看到,Extra: Using index 就表示使用到了覆盖索引,因为我的查询 SQL 中最终想要的值,都在当前这棵索引树上。

更进一步,假设我要查询 id、address 以及 age 字段,如下:

explain select id,address,age from user where username='ab'\G

70d4785e8b7e9baab363731340a96dd3.png很明显,由于这三个字段都在索引树上,所以直接直接通过回表获取到。

但是,如果想直接 select *,那么由于这个索引树上没有 gender 字段,此时就必须要回表才能拿到 gender 字段的值,如下:

explain select * from user where username='ab'\G

0edd14f4d29271e17533c86011a53092.png

可以看到,这个时候没有用到覆盖索引了。

3. 覆盖索引的优势

通过前面的介绍,覆盖索引的优势相信小伙伴们也能自己总结出来:

覆盖索引不需要回表,直接在 B+Tree 这颗索引树上就能读取到需要的数据,这极大的减少了数据库 IO 次数,在 IO 密集型应用中,这样的性能提升非常有效。

基于 B+Tree 中联合索引数据的排序规则,覆盖索引中,如果涉及到范围搜索,也是非常高效的(如果涉及到回表的话,效率就会降低很多)。


相关文章
|
7月前
|
SQL 存储 索引
12. 知道什么叫覆盖索引嘛 ?
**覆盖索引**是指在SQL查询中,索引包含所有所需列数据,避免回表查询,提高效率。创建覆盖索引可通过为查询字段建立联合索引,如在`user`表上为`name`和`age`创建`index_name_age`索引。查询`select name,age from user where name='Alice'`时,索引中已包含`name`和`age`,直接返回结果,实现覆盖索引。
63 0
12. 知道什么叫覆盖索引嘛 ?
|
6月前
|
SQL 关系型数据库 MySQL
MySQL数据库——索引(6)-索引使用(覆盖索引与回表查询,前缀索引,单列索引与联合索引 )、索引设计原则、索引总结
MySQL数据库——索引(6)-索引使用(覆盖索引与回表查询,前缀索引,单列索引与联合索引 )、索引设计原则、索引总结
124 1
|
存储 关系型数据库 MySQL
什么是覆盖索引?
本章主要讲解了索引覆盖和回表的相关知识
134 0
|
数据库 索引
覆盖索引
覆盖索引是指在数据库中创建一个索引,使得查询可以直接从索引中获取所需的数据,而不需要再去访问数据表。这种索引能够减少数据库的I/O操作,提高查询的性能。
78 0
|
7月前
|
存储 NoSQL 分布式数据库
Hbase的三种索引_全局索引,覆盖索引,本地索引(七)
Hbase的三种索引_全局索引,覆盖索引,本地索引(七)
208 0
|
存储 关系型数据库 MySQL
|
SQL 关系型数据库 MySQL
表索引——隐藏索引和删除索引
前言 MySQL 8开始支持隐藏索引。隐藏索引提供了更人性化的数据库操作。
|
存储 消息中间件 SQL
|
存储 SQL 关系型数据库
测试关于索引的操作- 修改索引
测试关于索引的操作- 修改索引

热门文章

最新文章