Mysql 索引下推和回表查询的关系?
·
Mysql 索引下推和回表查询是啥?
先来看看sql语句的部分执行流程:
-
Server层:通过优化器选择要使用的索引、将查询条件和索引发送到存储引擎层执行。
-
存储引擎层:根据索引扫描(遍历)符合条件的索引记录,然后将索引记录返回给Server层。
-
Server层:拿到过滤后的索引,判断是否需要回表(查询字段是否都存在于索引)。如果索引里没有所有的查询字段,则将索引中的主键们发送到存储引擎层。
比如索引
idx_a_bselect c from t where a = 5;
索引中没有c,需要通过主键回表拿到完整数据行,然后获取c
-
存储引擎层:根据主键,查询聚簇索引,得到完整的数据行,返回给Server层。
-
Server层:做最终过滤出查询的字段,返回数据。
什么是回表?
上述过程第三、四步。
在存储引擎层第一次过滤索引后,Server层再次将过滤后的索引发送给存储引擎层,过滤出对应的数据行(每一条索引记录,都需要通过主键到聚簇索引中查询)。这个过程就是回表。
什么是索引下推?
这是 Mysql 5.6+ 的新特性,一般作用于联合索引上。
抽象来讲 就是将where条件的部分判断下推到存储引擎层,在索引遍历过程中提前过滤,减少回表次数。是次数!
举个栗子:
联合索引:idx_name_age。
sql:SELECT * FROM users WHERE name like '张%' AND age = 18;
假设mysql 5.5 版本,没有索引下推机制。
此时的执行流程:
- Server层选择索引
idx_name_age、将条件和索引发送给引擎层 - 引擎层根据
name like '张%'条件、过滤出500条联合索引,返回到Server层 - Server层将索引对应主键发送到引擎层 回表500次,
- 引擎层根据主键查询到一条聚簇索引,返回数据行。
- Server层对数据行 判断是否满足 age = 18,如果满足,加入到返回的集合中。
- Server层返回数据集。
看看mysql 5.6+版本,有索引下推机制。
此时的执行流程:
- Server层选择索引
idx_name_age、将条件和索引发送给引擎层。逻辑不变 - 引擎层判断
name like '张%'的同时,会额外判断索引中age =18、最终过滤出50条联合索引,返回到Server层。 逻辑变了 - Server层将索引对应主键发送到引擎层 回表50次。逻辑不变
- 引擎层根据主键查询到一条聚簇索引,返回数据行。逻辑不变
- Server层直接返回数据集。变了
可以看到,将本来Server层判断
age = 18的逻辑,下推到了引擎层。
扩展
SQL:SELECT * FROM users WHERE name = '张三' AND age > 18;
此时引擎层可以直接通过索引扫描数据,无需下推。因为此时的检索条件在索引中是有序的
更多推荐

所有评论(0)