回表和索引覆盖介绍

本章中我们主要理解以下几个问题:

(1)基于主键索引和普通索引的查询有什么区别?

(2)怎么理解回表?

(3)怎么理解索引覆盖?

索引结构示例分析

在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。 InnoDB使用了B+树索引模型,所以数据都是存储在B+树中的。 每一个索引在InnoDB里面对应一棵B+树

假设,我们有一个主键列为ID的表,表中有字段k,并且在k上有索引。

这个表的建表语句是:

 表中R1~R5的(id,k)值分别为(100,1,’aa’)、(200,2,’bb’)、(300,3,’cc’)、(500,5,’dd’)和(600,6,’ee’),两棵树的示例示意图如下。

从图中不难看出,根据叶子节点的内容,索引类型分为主键索引和非主键索引

主键索引的叶子节点存的是整行数据。在InnoDB里,主键索引也被称为聚簇索引(clustered index)。

非主键索引的叶子节点内容是主键的值。在InnoDB里,非主键索引也被称为二级索引 (secondary index)。

根据上面的索引结构说明,我们来讨论一个问题:

基于主键索引和普通索引的查询有什么区别?怎么理解回表? 

(1)如果语句是select * from T where ID=500,即主键查询方式,则只需要搜索ID这棵B+树;

(2)如果语句是select * from T where k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID 的值为500,再到ID索引树搜索一次。这个过程称为回表

也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询

怎么理解覆盖索引?

当我们执行select * from T where k=5,由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有可能经过索引优化,避免回表过程呢?     

如果执行的语句是select ID fromTwhere k =5,这时只需要查ID的值,而ID的值已经在k索引树上了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面, 索引k已经“覆盖了”我们的查询需求,我们称为覆盖索引

由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用 的性能优化手段

面试中简要回答

平时在写SQL时应该尽量使用主键查询和覆盖索引,可以减少树的搜索次数也就是避免回表,从而提升查询性能。具体原理如下:

每一个索引在InnoDB里面对应一棵B+树。主键索引的叶子节点存的是整行数据,非主键索引的叶子节点内容是主键的值。好比我们有一个以id为主键的表,表中有个加了普通索引的字段K。

(1) 当我们查询select * from T where k=5时,需要先搜索k索引树,拿到主键的值后再到ID主键索引树上搜索一次。这个过程称为回表

(2)如果执行的语句是select ID from T where k =5,这时只需要查ID的值,而ID的值已经在k索引树上了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面, 索引k已经“覆盖了”我们的查询需求,我们称为覆盖索引

希望本文章对您有帮助,您的转发、点赞是我的创作动力,十分感谢。更多好文推荐,请关注我的微信公众号--JustJavaIt
原文地址:https://www.cnblogs.com/liaowenhui/p/15177782.html