覆盖索引并不是一种索引类型,也不是索引结构,只能算是一种索引策略。
什么是覆盖索引
覆盖索引:SQL只需要通过索引就可以返回查询所需要的数据,而不必通过二级索引查到主键之后再去查询数据。
首先要了解覆盖索引之前,你必须要了解什么是聚簇索引和非聚簇索引,还有一个必须要了解的就是回表,覆盖索引其实就是跟到底需不需要回表有直接的关系的。
什么是回表呢?
通俗的讲就是,如果索引的列在 select 所需获得的列中或者根据一次索引查询就能获得记录就不需要回表,如果 select 所需获得列中有大量的非索引列,索引就需要到表中找到相应的列的信息,这就叫回表。只有非聚簇索引是需要回表的,所以如果你懂得非聚簇索引的存储的结构,你自然就知道为啥需要回表了。
为什么需要覆盖索引
举例我们建了一张学生表,其中包含字段id设置主键索引、name设置普通索引、age(无处理),并向数据库中插入 4 条数据:
- (”小赵”, 10)
- (”小王”, 11)
- (”小李”, 12)
- (”小陈”, 13)
1 | CREATE TABLE `student` ( |
这里我们设置了主键为自增,那么此时数据库里数据为:
id | name | age |
---|---|---|
1 | 小赵 | 10 |
2 | 小王 | 11 |
3 | 小李 | 12 |
4 | 小陈 | 13 |
每一个索引在 InnoDB 里面对应一棵B+树,那么此时就存着两棵B+树。
可以发现区别在与叶子节点中,主键索引存储了整行数据,而非主键索引中存储的值为主键id, 在我们执行如下sql后:
SELECT age FROM student WHERE name = ‘小李’;
流程为:
- 在 name 索引树上找到名称为小李的节点 id 为03
- 从 id 索引树上找到id为 03 的节点 获取所有数据
- 从数据中获取字段命为 age 的值返回 12
在流程中从非主键索引树搜索回到主键索引树搜索的过程称为:回表,在本次查询中因为查询结果只存在主键索引树中,我们必须回表才能查询到结果;
如何优化,不需要回表呢?
以name和age两个字段建立联合索引,sql命令与建立后的索引树结构如下:
ALTER TABLE student ADD INDEX I_name_age(name, age);
那在我们再次执行如下sql后:
SELECT age FROM student WHERE name = ‘小李’;
流程为:
- 在name,age联合索引树上找到名称为小李的节点
- 此时节点索引里包含信息age 直接返回 12
此时不再需要回表
总结
覆盖索引即从非主键索引中就能查到的记录,而不需要查询主键索引中的记录,避免了回表的产生减少了树的搜索次数,显著提升性能。覆盖索引并不是一种索引类型,而是一种建索引的策略。