Skip to content

面试速答(先看这里)

**一句话结论:**覆盖索引(covering index)指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。

60秒标准回答:

覆盖索引(covering index)指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖

当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率

如,表covering_index_sample中有一个普通索引 idx_key1_key2(key1,key2)

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。
  • **要点2:**索引下推是 MySQL 5.6引入了一种优化技术,默认开启,使用SET optimizer_switch = ‘index_condition_pushdown=off’;可以将其关闭。
  • **要点3:**如果符合条件,则根据该索引来定位对应的数据,如果不符合,则直接reject掉。
  • **要点4:**所以当联合索引中,某个非前导列因为索引失效而要进行扫表并回表时,就可以进行索引下推优化了。
  • **要点5:**因为b字段因为类型不匹配导致索引失效了,但是通过下推优化其实是可以减少回表的次数的。

**记忆锚点:**MySQL → LIKE → SQL → covering_index_sample → lastname → zipcode

易错提醒:

  • 当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。

加分表达:

  • 当我们通过SQL语句: select key2 from covering_index_sample where key1 = ‘keytest’; 的时候,就可以通过覆盖索引查询,无需回表。
  • 但是以下SQL,因为不符合最左前缀匹配,虽然是索引覆盖,但是也无法用到索引(会扫描索引树): select key1 from covering_index_sample where key2 = ‘keytest’; 但是如果SQL中查询的信息不包含在联合索引中,那么就不会走索引覆盖。
  • 如果使用了索引下推技术,则MYSQL首先会返回符合zipcode=’95054’的索引,然后根据lastname LIKE ‘%etrunia%’来判断索引是否符合条件。

追问准备:

  • 围绕「MySQL」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「LIKE」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「SQL」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

覆盖索引 ​

覆盖索引(covering index)指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖。

当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。

如,表covering_index_sample中有一个普通索引 idx_key1_key2(key1,key2)。

当我们通过SQL语句:

select key2 from covering_index_sample where key1 = ‘keytest’;

的时候,就可以通过覆盖索引查询,无需回表。

但是以下SQL,因为不符合最左前缀匹配,虽然是索引覆盖,但是也无法用到索引(会扫描索引树):

select key1 from covering_index_sample where key2 = ‘keytest’;

但是如果SQL中查询的信息不包含在联合索引中,那么就不会走索引覆盖。如:

select key2,key3 from covering_index_sample where key1 = ‘keytest’;

索引下推 ​

索引下推是 MySQL 5.6引入了一种优化技术,默认开启,使用SET optimizer_switch = ‘index_condition_pushdown=off’;可以将其关闭。

官方文档中给的例子和解释如下: people表中(zipcode,lastname,firstname)构成一个索引

SELECT * FROM people WHERE zipcode=’95054′ AND lastname LIKE ‘%etrunia%’ AND address LIKE ‘%Main Street%’;

如果没有使用索引下推技术,则MySQL会通过zipcode=’95054’从存储引擎中查询对应的数据,返回到MySQL服务端,然后MySQL服务端基于lastname LIKE ‘%etrunia%’和address LIKE ‘%Main Street%’来判断数据是否符合条件。

如果使用了索引下推技术,则MYSQL首先会返回符合zipcode=’95054’的索引,然后根据lastname LIKE ‘%etrunia%’来判断索引是否符合条件。

如果符合条件,则根据该索引来定位对应的数据,如果不符合,则直接reject掉。 有了索引下推优化,可以在有like条件查询的情况下,减少回表次数。

当一条SQL使用到索引下推时,explain的执行计划中的extra字段中内容为:Using index condition

索引下推不止like ​

上面的例子中,提到了like,包括MySQL官网中也只提到了like,但是其实不止有Like。因为我认为索引下推其实是解决索引失效带来的效率低的问题的一种手段。

所以当联合索引中,某个非前导列因为索引失效而要进行扫表并回表时,就可以进行索引下推优化了。

如,有a,b联合索引,类型都是varchar,以下SQL也可以用到索引下推:

plain
select d from t2 where a = "ni" and b = 1;

因为b字段因为类型不匹配导致索引失效了,但是通过下推优化其实是可以减少回表的次数的。