MySQL索引下推知识分享
来源 | OSCHINA 社区
作者 | 京东云开发者-刘邓忠
原文链接:https://my.oschina.net/u/4090830/blog/5613584
1 什么是索引下推
1.1 适用条件
只支持 select。
当需要访问全表时,ICP 用于 range,ref,eq_ref 和 ref_or_null 访问类型。
ICP 可用于 InnoDB 和 MyISAM 表,包括分区的 InnoDB 和 MyISAM 表。(5.6 版本不适用分区表查询,5.7 版本后可以用于分区表查询)。
对于 InnDB 引擎只适用于二级索引(也叫辅助索引),因为 InnDB 的聚簇索引会将整行数据读到 InnDB 的缓冲区,这样一来索引条件下推的主要目的减少 IO 次数就失去了意义。因为数据已经在内存中了,不再需要去读取了。
在虚拟生成列上创建的辅助索引不支持 ICP(注:InnoDB 支持虚拟生成列的辅助索引)。
使用了子查询的条件无法下推。
使用存储过程或函数的条件无法下推(因为因为存储引擎没有调用存储过程或函数的能力)。
触发条件无法下推。(有关触发条件的信息,请参阅官方资料:Section 8.2.2.3, “Optimizing Subqueries with the EXISTS Strategy”.。)
1.2 原理介绍
MySQL 基本的架构示例图
索引下推的下推其含义就是指将部分上层(服务层)负责的事情,交给了下层(引擎层)去处理。
在 MySql 5.6 版本之前没有索引下推这个功能,从 5.6 版本后才加上了这个优化项。我们先简单对比一下使用和未使用 ICP 两种情况下,MySql 的查询过程吧。
1) 未使用 ICP 的情况下:
- 存储引擎读取索引记录;
- 根据索引中的主键值,定位并读取完整的行记录;
- 存储引擎把记录交给 Server 层去检测该记录是否满足 WHERE 条件。
2) 使用 ICP 的情况下:
- 存储引擎读取索引记录(不是完整的行记录);
- 判断 WHERE 条件部分能否用索引中的列来做检查,条件不满足,则处理下一行索引记录;
- 条件满足,使用索引中的主键去定位并读取完整的行记录(就是所谓的回表);
- 存储引擎把记录交给 Server 层,Server 层检测该记录是否满足 WHERE 条件的其余部分。
2 具体示例
首先,我们新建一张用户表(jxc_user),设置 id 为主键索引,并创建联合索引(name, age)。
主键索引结构示例图
联合索引结构示例图
select id,name,age,tel,addr from jxc_user where name like '张%' and age=10;
那接下来我们具体看一下 使用与未使用 ICP 的情况。
2.1 未使用 ICP 的情况
2.2 使用 ICP 的情况
3 控制参数
查看状态命令:
select @@optimizer_switch;
开启命令:set optimizer_switch=”index_condition_pushdown=on”;
4 总结
索引下推:索引下推主要是减少了不必要的回表操作。对于查找出来的数据,先过滤掉不符合条件的,其余的再去主键索引树上查找。
5 参考文献
https://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html
http://mysql.taobao.org/monthly/2015/12/08/
往期推荐
微软工程师展望Rust 2023:重写编译器、解决管理问题
英特尔发布新的 “Xe” Linux 内核图形驱动程序
招募不到维护者,Go语言Web工具包Gorilla归档
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦~
微信扫码关注该文公众号作者