Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 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.01'。这意味着无法使用任何索引来优化字符串列的查询。

  • 为了找到特定索引列 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节,“避免全表扫描”