文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  索引条件下推优化

10.2.1.6 索引条件下推优化

索引条件下推(ICP)是一种针对 MySQL 使用索引从表中检索行的优化。如果没有 ICP,存储引擎会遍历索引以找到基表中的行,并将它们返回给 MySQL 服务器,后者会评估这些行的 WHERE 条件。启用 ICP 后,如果 WHERE 条件的某些部分仅使用索引中的列即可评估,则 MySQL 服务器会将这部分 WHERE 条件下推到存储引擎。然后,存储引擎使用索引条目评估下推的索引条件,并且只有在满足该条件时,才会从表中读取该行。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 节“可切换优化”。