MySQL索引:回表、索引覆盖,最左匹配原则、索引下推

Source

一、回表

若有student表如下

id(主键) name age
1 路飞 18
2 索隆 20

我们对id建立索引,然后再对name建立索引。那么当我们执行select * from  student where name=?时,由于索引底层数据结构的B+Tree,对name列建立的索引叫做二级索引或者副主索引,这个索引的数据存储的是id(或者唯一列、或者是6字节的row id),如下图,那么我们执行完SQL时,会从name的B+Tree中拿到id,再回到id的B+Tree中去搜索所对应的数据,这个过程就叫做回表

 

二、索引覆盖

还是,假设有两条语句

select * from  student where name=?

select id from  student where name=?

此时,就不会再去再去id的对应索引的那颗B+Tree上再去搜索一遍了,这就是索引覆盖

三、最左匹配原则

一帮情况下和组合索引一起使用,例如吧name,age共同建立索引(name,age),假设现在有下面四条sql语句

select * from  student where name=? and age=?

select * from  student where name=?

select * from  student where age=?

select * from  student where age=? and name=?

现在问题来了,那个会走组合索引(name,age)?

答案是1,2,4,而3会进行全表扫描,看下图

听名知意,就是最左边开始匹配呗,也就是先匹配name,再来age。虽然2只有name,但是也会走索引。

你可能的疑惑就是4为啥会走索引,其实mysql中有个叫做优化器的东西,他会对这个age和name的顺序进行优化。这样就可以走索引了

优化器简单的说一下,有两种:CBO(基于成本的优化)RBO(基于规则的优化)MySQL默认用的是CBO。

四、索引下推

首先:

数据是存储在磁盘的、MySQL有自己的服务,MySQL服务要跟磁盘发生交互。这样能从磁盘拿到数据

没有索引下推时:

存储引擎先从磁盘中筛选出name符合条件的数据,全部取出,MySQL server再根据age条件筛选一次。这样就得到了符合条件的值。

这样会有大量的IO操作,所以浪费时间和资源

有存索引下推时:

存储引擎先从磁盘中直接筛选出name,age同时都符合条件的数据,不需要server再去做任何的数据筛选

索引下推需要在磁盘上进行数据筛选,原来的筛选是在内存中进行,现在放到了磁盘上进行查找数据的环节,但是,虽然这样看起来成本更高了,可别忘了,索引数据是排序的,所有数据是聚集存放的没所以性能并不会有影响,而且还会减少IO次数,反而会提升性能