mysql Using index condition
explain mysql 语句,在extra栏里出现 Using index condition 很好奇为什么呢? 是好还是不好?
首先 肯定答案: 是好的!
解释:
Using index condition 叫作 Index Condition Pushdown Optimization (索引下推优化)。
Index Condition Pushdown (ICP)是MySQL使用索引从表中检索行的一种优化。如果没有ICP,存储引擎将遍历索引以定位表中的行,并将它们返回给MySQL服务器,服务器将判断行的WHERE条件。在启用ICP的情况下,如果可以只使用索引中的列来计算WHERE条件的一部分,MySQL服务器就会将WHERE条件的这一部分推到存储引擎中。然后,存储引擎通过使用索引条目来评估推入的索引条件,只有当满足该条件时,才从表中读取行。ICP可以减少存储引擎必须访问基表的次数和MySQL服务器必须访问存储引擎的次数。
ICP的适用性取决于以下条件:
1.当需要访问整个表行时,ICP用于range、ref、eq_ref和ref_or_null访问方法。
2.ICP可以用于InnoDB和MyISAM表,包括分区的InnoDB和MyISAM表。
3.对于InnoDB表,ICP仅用于二级索引。ICP的目标是减少全行读取的数量,从而减少I/O操作。对于InnoDB聚集索引,完整的记录已经被读取到InnoDB缓冲区中。在这种情况下使用ICP并不会减少I/O。
4.在虚拟生成的列上创建二级索引不支持ICP。InnoDB支持在虚拟生成的列上建立二级索引。
5.引用子查询的条件不能下推。
6.引用存储函数的条件不能下推。存储引擎无法调用存储函数。
7.触发的条件不能被压制。
7.触发的条件不能被压制。
要理解 ICP 这种优化是如何工作的,首先考虑当没有使用ICP时索引扫描是如何进行的:
1.获取下一行,首先通过读取索引元组,然后使用索引元组定位和读取整个表行。
2.检查WHERE条件中应用于此表的部分。根据检查结果接受或拒绝行。
使用ICP,则会变成下面这样:
1.获取下一行的索引元组(但不是整个表行)。
2.检查应用于此表的WHERE条件的部分,仅使用索引列即可进行检查。如果条件不满足,则进入下一行的索引元组。(因为索引条件下推到了存储引擎层)
3.如果条件满足,则使用index元组定位和读取整个表行。
4.测试应用于此表的WHERE条件的其余部分。根据测试结果接受或拒绝行
4.测试应用于此表的WHERE条件的其余部分。根据测试结果接受或拒绝行
例子:
假设一个表包含关于人员及其地址的信息,并且该表有一个定义为index (zipcode, lastname, firstname)的索引。如果我们知道一个人的zipcode值,但不确定他的姓氏,我们可以这样搜索:
SELECT * FROM people WHERE zipcode='95054' AND lastname LIKE '%etrunia%' AND address LIKE '%Main Street%';
MySQL可以使用索引扫描邮编为'95054'的人。第二部分(lastname LIKE '%etrunia%')不能用于限制必须扫描的行数,因此如果没有ICP,该查询必须检索zipcode='95054'的所有人的完整表行。使用ICP,MYSQL在读取全部行表时,可以先检查
lastname LIKE '%etrunia%' 的部分,这样避免了那部分多的数据的返回。
官方文档解释:https://dev.mysql.com/doc/refman/5.7/en/index-condition-pushdown-optimization.html