Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Index Condition Pushdown Optimization

10.2.1.6 索引条件下推优化

索引条件下推(ICP)是 MySQL 检索表行时使用索引的一种优化。没有 ICP,存储引擎会遍历索引以定位基表中的行,并将其返回给 MySQL 服务器,以评估 WHERE 条件。启用 ICP 后,如果 WHERE 条件的一部分可以仅使用索引中的列来评估,那么 MySQL 服务器将该部分条件下推到存储引擎。然后,存储引擎使用索引条目来评估下推的索引条件,只有在满足条件时才读取表中的行。ICP 可以减少存储引擎访问基表的次数和 MySQL 服务器访问存储引擎的次数。

索引条件下推优化的适用性取决于以下条件:

  • ICP 用于 rangerefeq_refref_or_null 访问方法时,需要访问完整的表行。

  • ICP 可用于 InnoDBMyISAM 表,包括分区的 InnoDBMyISAM 表。

  • 对于 InnoDB 表,ICP 只用于辅助索引。ICP 的目标是减少完整行的读取次数,从而减少 I/O 操作。对于 InnoDB 聚集索引,完整的记录已经读取到 InnoDB 缓冲区中。在这种情况下,使用 ICP 不会减少 I/O。

  • ICP 不支持在虚拟生成列上创建的辅助索引。InnoDB 支持在虚拟生成列上创建的辅助索引。

  • 不能将涉及子查询的条件下推。

  • 不能将涉及存储函数的条件下推。存储引擎不能调用存储函数。

  • 触发的条件不能下推。(有关触发的条件,请参阅 第 10.2.2.3 节,“使用 EXISTS 策略优化子查询”。)

  • 不能将涉及系统变量的条件下推到派生表中。

要了解这个优化是如何工作的,首先考虑没有使用索引条件下推时的索引扫描过程:

  1. 获取下一行,首先读取索引元组,然后使用索引元组定位和读取完整的表行。

  2. 测试应用于该表的 WHERE 条件的一部分。根据测试结果接受或拒绝该行。

使用索引条件下推,扫描过程如下:

  1. 获取下一行的索引元组(但不是完整的表行)。

  2. 测试应用于该表的 WHERE 条件的一部分,可以使用索引列来检查。如果条件不满足,则继续下一行的索引元组。

  3. 如果条件满足,则使用索引元组定位和读取完整的表行。

  4. 测试剩余的 WHERE 条件的一部分。根据测试结果接受或拒绝该行。

EXPLAIN 输出在 Extra 列中显示 Using index condition,以指示使用了索引条件下推。它不显示 Using index,因为这不适用于必须读取完整表行的情况。

假设一个表包含关于人的信息和地址,并且该表有一个索引定义为 INDEX (zipcode, lastname, firstname)。如果我们知道某人的 zipcode 值,但不确定姓氏,我们可以这样搜索:

SELECT * FROM people
  WHERE zipcode='95054'
  AND lastname LIKE '%etrunia%'
  AND address LIKE '%Main Street%';

MySQL 可以使用索引来扫描具有 zipcode='95054' 的人。第二部分 (lastname LIKE '%etrunia%') 不能用于限制必须扫描的行数,因此没有索引条件下推,这个查询必须检索具有 zipcode='95054' 的所有人的完整表行。

使用索引条件下推,MySQL 在读取完整表行之前检查 lastname LIKE '%etrunia%' 部分。这避免了读取完整行,相应的索引元组匹配 zipcode 条件但不匹配 lastname 条件。

索引条件下推默认启用。可以使用 optimizer_switch 系统变量通过设置 index_condition_pushdown 标志来控制:

SET optimizer_switch = 'index_condition_pushdown=off';
SET optimizer_switch = 'index_condition_pushdown=on';

参见 第 10.9.2 节,“可切换优化”