文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  MySQL 如何使用索引

10.3.1 MySQL 如何使用索引

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

大多数 MySQL 索引(PRIMARY KEYUNIQUEINDEXFULLTEXT)都存储在 B 树 中。例外情况:空间数据类型的索引使用 R 树;MEMORY 表也支持 哈希索引InnoDBFULLTEXT 索引使用倒排列表。

通常,索引的使用方式如下所述。哈希索引(如 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() 值。这是通过预处理器优化的,该预处理器检查您是否在索引中 key_col 之前出现的所有键部分上使用 WHERE key_part_N = constant。在这种情况下,MySQL 对每个 MIN()MAX() 表达式执行一次键查找,并将其替换为常量。如果所有表达式都被替换为常量,则查询将立即返回。例如

    SELECT MIN(key_part2),MAX(key_part2)
      FROM tbl_name WHERE key_part1=10;
  • 如果排序或分组是在可用索引的最左侧前缀上完成的(例如,ORDER BY key_part1, key_part2),则对表进行排序或分组。如果所有键部分后都跟着 DESC,则按相反顺序读取键。(或者,如果索引是降序索引,则按顺序读取键。)请参阅“第 10.2.1.16 节 “ORDER BY 优化”“第 10.2.1.17 节 “GROUP BY 优化”“第 10.3.13 节 “降序索引”

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

    SELECT key_part3 FROM tbl_name
      WHERE key_part1=1

对于小型表或大型表(其中报表查询处理了大部分或所有行)的查询,索引不太重要。当查询需要访问大部分行时,顺序读取比通过索引工作要快。顺序读取最大程度地减少了磁盘搜索,即使查询不需要所有行也是如此。有关详细信息,请参阅“第 10.2.1.23 节 “避免全表扫描”