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  /  ...  /  How MySQL Uses Indexes

10.3.1 MySQL 是如何使用索引的

索引用于快速找到具有特定列值的行。没有索引,MySQL 必须从第一行开始,然后读取整个表以找到相关行。表越大,这个成本越高。如果表具有相关列的索引,MySQL 可以快速确定数据文件中的位置,而不需要查看所有数据。这比顺序读取每一行要快得多。

大多数 MySQL 索引 (PRIMARY KEYUNIQUEINDEXFULLTEXT) 都存储在 B 树 中。例外:空间数据类型的索引使用 R 树;MEMORY 表也支持 哈希索引InnoDB 使用反转列表来存储 FULLTEXT 索引。

一般来说,索引按照以下讨论所述使用。哈希索引(如在 MEMORY 表中使用)特征在 第 10.3.9 节,“B 树和哈希索引的比较” 中描述。

MySQL 使用索引来执行以下操作:

  • 快速找到与 WHERE 子句匹配的行。

  • 排除行以减少考虑的行数。如果有多个索引可供选择,MySQL 通常使用找到最少行数的索引(最 选择性 的索引)。

  • 如果表具有多列索引,任何左侧前缀索引都可以由优化器用于查找行。例如,如果您有一个三列索引 (col1, col2, col3),那么您在 (col1)(col1, col2)(col1, col2, col3) 上都有索引搜索功能。有关更多信息,请参阅 第 10.3.6 节,“多列索引”

  • 在执行连接时,从其他表中检索行。MySQL 可以更高效地使用索引,如果它们被声明为相同的类型和大小。在这个上下文中,VARCHARCHAR 被认为是相同的大小。例如,VARCHAR(10)CHAR(10) 是相同的大小,但 VARCHAR(10)CHAR(15) 不是。

    对于非二进制字符串列的比较,两个列都应该使用相同的字符集。例如,比较 utf8mb4 列与 latin1 列将阻止使用索引。

    比较不同类型的列(例如比较字符串列与时间或数字列)可能会阻止使用索引,如果值不能直接比较而不需要转换。例如,对于数字列中的特定值 1,它可能与字符串列中的多个值相等,例如 '1'' 1''00001''01.e1'。这排除了字符串列的索引使用。

  • 找到特定索引列 key_colMIN()MAX() 值。这通过预处理器来优化,该预处理器检查您是否使用 WHERE key_part_N = constant 在所有 key 部分中,该部分出现在索引中的 key_col 之前。在这种情况下,MySQL 对每个 MIN()MAX() 表达式执行单个键查找,并将其替换为常量。如果所有表达式都被替换为常量,查询将立即返回。例如:

    SELECT MIN(key_part2),MAX(key_part2)
      FROM tbl_name WHERE key_part1=10;
  • 如果对表进行排序或分组,并且排序或分组是基于可用索引的左most前缀(例如,ORDER BY key_part1, key_part2)。如果所有键部分都跟随 DESC,则键将以逆序读取。(或者,如果索引是降序索引,键将以正序读取。)请参阅 第 10.2.1.16 节,“ORDER BY 优化”第 10.2.1.17 节,“GROUP BY 优化”第 10.3.13 节,“降序索引”

  • 在某些情况下,查询可以被优化以从不consult数据行中检索值。(提供所有必要结果的索引称为 覆盖索引。)如果查询仅从表中使用某些列,而这些列都包含在某个索引中,那么可以从索引树中检索所需值,以提高速度:

    SELECT key_part3 FROM tbl_name
      WHERE key_part1=1

对于小表或大表中的报告查询处理大多数或所有行,索引变得不那么重要。当查询需要访问大多数行时,顺序读取比通过索引工作更快。顺序读取可以最小化磁盘寻道,即使查询不需要所有行。请参阅 第 10.2.1.23 节,“避免全表扫描” 了解详情。