Index Condition Pushdown (ICP) is an optimization for the case where MySQL retrieves rows from a table using an index. 索引条件下推(ICP)是MySQL使用索引从表中检索行的一种优化。Without ICP, the storage engine traverses the index to locate rows in the base table and returns them to the MySQL server which evaluates the 如果没有ICP,存储引擎将遍历索引以定位基表中的行,并将它们返回给MySQL服务器,该服务器将评估行的WHERE
condition for the rows. WHERE
条件。With ICP enabled, and if parts of the 启用ICP后,如果WHERE
condition can be evaluated by using only columns from the index, the MySQL server pushes this part of the WHERE
condition down to the storage engine. WHERE
条件的一部分可以仅使用索引中的列进行评估,则MySQL服务器会将WHERE
条件的这一部分向下推送到存储引擎。The storage engine then evaluates the pushed index condition by using the index entry and only if this is satisfied is the row read from the table. 然后,存储引擎使用索引项评估推送索引条件,只有满足此条件时,才会从表中读取行。ICP can reduce the number of times the storage engine must access the base table and the number of times the MySQL server must access the storage engine.ICP可以减少存储引擎必须访问基表的次数和MySQL服务器必须访问存储引擎的次数。
Applicability of the Index Condition Pushdown optimization is subject to these conditions:指标条件下推优化的适用性取决于以下条件:
ICP is used for the 当需要访问完整表行时,ICP用于range
, ref
, eq_ref
, and ref_or_null
access methods when there is a need to access full table rows.range
、ref
、eq_ref
和ref_or_null
访问方法。
ICP can be used for ICP可用于InnoDB
and MyISAM
tables, including partitioned InnoDB
and MyISAM
tables.InnoDB
和MyISAM
表,包括分区的InnoDB
和MyISAM
表。
For 对于InnoDB
tables, ICP is used only for secondary indexes. InnoDB
表,ICP仅用于辅助索引。The goal of ICP is to reduce the number of full-row reads and thereby reduce I/O operations. ICP的目标是减少整行读取的数量,从而减少I/O操作。For 对于InnoDB
clustered indexes, the complete record is already read into the InnoDB
buffer. InnoDB
聚集索引,已将完整记录读入InnoDB
缓冲区。Using ICP in this case does not reduce I/O.在这种情况下使用ICP不会减少I/O。
ICP is not supported with secondary indexes created on virtual generated columns. 在虚拟生成的列上创建的二级索引不支持ICP。InnoDB
supports secondary indexes on virtual generated columns.InnoDB
支持虚拟生成列上的辅助索引。
Conditions that refer to subqueries cannot be pushed down.引用子查询的条件不能向下推。
Conditions that refer to stored functions cannot be pushed down. 无法按下与存储函数相关的条件。Storage engines cannot invoke stored functions.存储引擎无法调用存储函数。
Triggered conditions cannot be pushed down. 触发的条件不能向下推。(For information about triggered conditions, see Section 8.2.2.3, “Optimizing Subqueries with the EXISTS Strategy”.)(有关触发条件的信息,请参阅第8.2.2.3节,“使用EXISTS策略优化子查询”。)
To understand how this optimization works, first consider how an index scan proceeds when Index Condition Pushdown is not used:要理解这种优化是如何工作的,首先考虑索引扫描不使用索引条件推送时如何进行:
Get the next row, first by reading the index tuple, and then by using the index tuple to locate and read the full table row.获取下一行,首先读取索引元组,然后使用索引元组定位并读取整个表行。
Test the part of the 测试适用于此表的WHERE
condition that applies to this table. WHERE
条件部分。Accept or reject the row based on the test result.根据测试结果接受或拒绝该行。
Using Index Condition Pushdown, the scan proceeds like this instead:使用“索引条件”下推,扫描按如下方式进行:
Get the next row's index tuple (but not the full table row).获取下一行的索引元组(但不是完整的表行)。
Test the part of the 测试适用于此表且只能使用索引列进行检查的WHERE
condition that applies to this table and can be checked using only index columns. WHERE
条件部分。If the condition is not satisfied, proceed to the index tuple for the next row.如果不满足条件,则转至下一行的索引元组。
If the condition is satisfied, use the index tuple to locate and read the full table row.如果满足条件,则使用索引元组查找并读取完整的表行。
Test the remaining part of the 测试适用于此表的WHERE
condition that applies to this table. WHERE
条件的其余部分。Accept or reject the row based on the test result.根据测试结果接受或拒绝该行。
EXPLAIN
output shows Using index condition
in the Extra
column when Index Condition Pushdown is used. EXPLAIN
输出显示在使用索引条件下推时在Extra
列中Using index condition
。It does not show 它不显示Using index
because that does not apply when full table rows must be read.Using index
,因为当必须读取完整的表行时,这不适用。
Suppose that a table contains information about people and their addresses and that the table has an index defined as 假设一个表包含有关人员及其地址的信息,并且该表有一个定义为INDEX (zipcode, lastname, firstname)
. INDEX (zipcode, lastname, firstname)
的索引。If we know a person's 如果我们知道一个人的zipcode
value but are not sure about the last name, we can search like this:zipcode
值,但不确定姓氏,我们可以这样搜索:
SELECT * FROM people WHERE zipcode='95054' AND lastname LIKE '%etrunia%' AND address LIKE '%Main Street%';
MySQL can use the index to scan through people with MySQL可以使用索引扫描zipcode='95054'
. zipcode='95054'
的用户。The second part (第二部分(lastname LIKE '%etrunia%'
) cannot be used to limit the number of rows that must be scanned, so without Index Condition Pushdown, this query must retrieve full table rows for all people who have zipcode='95054'
.lastname LIKE '%etrunia%'
)不能用于限制必须扫描的行数,因此,如果没有索引条件下推,此查询必须为所有zipcode='95054'
的用户检索完整的表行。
With Index Condition Pushdown, MySQL checks the 按下索引条件,MySQL会在读取完整表行之前检查lastname LIKE '%etrunia%'
part before reading the full table row. lastname LIKE '%etrunia%'
部分。This avoids reading full rows corresponding to index tuples that match the 这样可以避免读取与zipcode
condition but not the lastname
condition.zipcode
条件(而不是lastname
条件)匹配的索引元组对应的整行。
Index Condition Pushdown is enabled by default. 默认情况下启用“索引条件”下推。It can be controlled with the 通过设置optimizer_switch
system variable by setting the index_condition_pushdown
flag:index_condition_pushdown
标志,可以使用optimizer_switch
系统变量对其进行控制:
SET optimizer_switch = 'index_condition_pushdown=off'; SET optimizer_switch = 'index_condition_pushdown=on';
See Section 8.9.2, “Switchable Optimizations”.请参阅第8.9.2节,“可切换的优化”。