一:简介
索引条件下推优化(Index Condition Pushdown (ICP) )
是 MySQL5.6 添加的,用于优化数据查询。
- 不使用索引条件下推优化时存储引擎通过索引检索到数据,然后返回给 MySQL Server,MySQL Server 进行过滤条件的判断。
- 当使用索引条件下推优化时,如果存在某些被索引的列的判断条件时,MySQL Server 将这一部分判断条件下推给存储引擎,然后由存储引擎通过判断索引是否符合 MySQL Server 传递的条件,只有当索引符合条件时才会将数据检索出来返回给 MySQL 服务器。
二:举例
首先,我们创建一张user
表,同时建立age_name
的联合索引,同时插入3条测试数据。
然后,我们执行查询:
sql
代码解读
复制代码
select * from t_user where name like '张%' and age=10;
按照我们上述的场景,实际上就存在两个索引树,一个是主键索引,存储了具体的数据的信息,另外则是age_name
的联合索引,保存了主键的ID。
在没有ICP索引下推的时候,这个查询的流程应该是这样(略过无关的细节):
- Mysql Server层调用API查询存储引擎数据
- 存储引擎根据联合索引首先通过条件找到所有age>10的数据
- 找到的每一条数据都根据主键索引进行回表查询,直到找到不符合条件的结果
- 返回数据给Server层,Server根据条件对结果进行过滤,流程结束
而有了ICP之后的流程则是这样:
- Mysql Server层调用API查询存储引擎数据
- 存储引擎根据联合索引首先通过条件找到所有age>10的数据,根据联合索引中已经存在的
name
数据进行过滤,找到符合条件的数据 - 根据找到符合条件的数据,回表查询
- 返回数据给Server层,流程结束
三:总结
对比这两个流程就会很明显的发现,使用ICP之后我们就是简单的通过联合索引中本来就有的数据直接过滤了,不需要再查到一堆无用的数据去Server层进行过滤,这样的话减少了回表的次数和返回的数据,IO次数减少了,对性能有很好的提升。
索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少 MySQL 服务器从存储引擎接收数据的次数。
按照官方文档所说,ICP其实也存在一定的使用限制场景,只说关键的,乱七八糟的不说。
- 首先,ICP适用于range、ref、eq_ref和ref_or_null的场景下
- InnoDB和MyISAM都支持ICP,Mysql partition分表的话也可以使用
- 对于InndoDB而言,ICP只支持二级索引,因为主键索引它用不上不是吗?
- 子查询不支持
现在我们基本都使用的5.6以上的版本了,默认就是开启ICP的,想关闭的话可以通过命令SET optimizer_switch = 'index_condition_pushdown=off';
。