天天看点

面试数据库中索引下推、覆盖索引,你会了吗

作者:打篮球的程序员

一、覆盖索引

首先看下创建的索引:

面试数据库中索引下推、覆盖索引,你会了吗

比如:现在有个场景是根据ep_id查询name,对应的sql应该是:

select name from ep where ep_id = '123'

但是ep_id 和name的并不是在一个索引树上,那么根就要根据ep_id的索引然后对应的主键Id,然后再根据ID去聚簇索引上找到对应的name值,这样其实绕了一大圈,也就是我们所说的回表。

如果ep_id和name是在一个索引树上,就可以直接根据ep_id找到对应的name值,索引ep_id 已经 “覆盖了” 我们的查询需求,我们称为 覆盖索引。

面试数据库中索引下推、覆盖索引,你会了吗

二:索引下推

都知道mysql匹配索引是满足要满足最左前缀原则的,最左前缀可以用于在索引中定位记录。那么如果那些不符合最左前缀的部分,会怎么样呢?

select * from t_user where name like '张%' and is_del=1
  • 在MySQL 5.6之前,只能从匹配的位置一个个回表。到主键索引上找出数据行,再对比字段值
  • 在MySQL 5.6中 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

根据(name,is_del)联合索引查询所有满足名称以“张”开头的索引,然后回表查询出相应的全行数据,然后再筛选出未删除的用户数据。过程如下图:

面试数据库中索引下推、覆盖索引,你会了吗

无索引下推执行流程

面试数据库中索引下推、覆盖索引,你会了吗

索引下推执行流程

图1跟图2的区别是,InnoDB在(name,is_del)索引内部就判断了数据是否逻辑删除,对于逻辑删除的记录,直接判断并跳过。在我们的这个例子中,只需要对ID1、ID4这两条记录回表取数据判断,就只需要回表2次

mysql默认启用索引下推,我们也可以通过修改系统变量optimizer_switch的index_condition_pushdown标志来控制SET optimizer_switch = 'index_condition_pushdown=off';

我们也需要注意:

  • innodb引擎的表,索引下推只能用于二级索引,因为innodb的主键索引树叶子结点上保存的是全行数据,所以这个时候索引下推并不会起到减少查询全行数据的效果
  • 索引下推一般可用于所求查询字段(select列)不是/不全是联合索引的字段,查询条件为多条件查询且查询条件子句(where/order by)字段全是联合索引
面试数据库中索引下推、覆盖索引,你会了吗

继续阅读