Mysql必知必会之回表和覆盖索引

回表

讲完Mysql必知必会之二级索引,接下来讲一讲如何使用二级索引查找数据。这里假设对name字段创建了一个索引,并且表里就存了上面示例中的几条数据,这里我再把图拿过来

那么对于下面这条sql应该如何执行?

select * from `user` where name = '赵六';

由于查询条件是name = '赵六',所以会走name索引。整个过程大致分为以下几个步骤:

  • 从最上面那层索引页开始二分查找,我们图中就是索引页113,如果索引页113上面还有一层,就从上面一层二分查找
  • 在索引页113查找到赵六王五刘七之间,之后到王五对应的索引页111上去查找赵六
  • 在索引页111找到赵六的第一条记录,也就是id=4的那条
  • 由于是select *,还要查其它字段,此时就会根据id=4到聚簇索引中查找其它字段数据,这个查找过程前面说了很多次了,这个根据id=4到聚簇索引中查找数据的过程就被称为回表
  • 由于是非唯一索引,所以赵六这个值可能会有重复,所以接着就会在索引页111顺着链表继续遍历,如果name还是赵六,那么还会根据id值进行回表,如此重复,一直这么遍历,直至name不再等于赵六为止,对于图示,其实就是两条数据

从上面的二级索引的查找数据过程分析,就明白了回表的意思,就是先从二级索引根据查询条件字段值查找对应的主键id,之后根据id再到聚簇索引查找其它字段的值。

覆盖索引

上一节说当执行select * from user where name = '赵六';这条sql的时候,会先从索引页中查出来name = '赵六';对应的主键id,之后再回表,到聚簇索引中查询其它字段的值。那么当执行下面这条sql,又会怎样呢?

select id from `user` where name = '赵六';

这次查询字段从select *变成select id,查询条件不变,所以也会走name索引。所以还是跟前面一样了,先从索引页中查出来name = '赵六';对应的主键id之后,惊讶的发现,sql中需要查询字段的id值已经查到了,那次此时压根就不需要回表了,已经查到id了,还回什么表。而这种需要查询的字段都在索引列中的情况就被称为覆盖索引,索引列覆盖了查询字段的意思。当使用覆盖索引时会减少回表的次数,这样查询速度更快,性能更高。所以,在日常开发中,尽量不要select * ,需要什么查什么,如果出现覆盖索引的情况,查询会快很多。

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/131030711