Skip to main content

1.MySQL如何使用索引

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

大多数 MySQL 索引(PRIMARY KEY、UNIQUE、INDEX 和 FULLTEXT)都存储在 B 树中。 例外:空间数据类型的索引使用 R 树; MEMORY表还支持哈希索引; InnoDB 对 FULLTEXT 索引使用倒排列表。

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

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

  • 从考虑中消除行。 如果在多个索引之间进行选择,MySQL通常会使用找到最少行数的索引(最具选择性的索引)。

  • 如果表具有多列索引,则优化器可以使用索引的任何最左边的前缀来查找行。 例如,如果您在 (col1, col2, col3) 上有一个三列索引,则您在 (col1)、(col1, col2) 和 (col1, col2, col3) 上具有索引搜索功能。

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

    对于非二进制字符串列之间的比较,两列应使用相同的字符集。 例如,将 utf8mb4 列与 latin1 列进行比较会排除索引的使用。

    如果无法在不进行转换的情况下直接比较值,则比较不同的列(例如,将字符串列与时间列或数字列进行比较)可能会阻止使用索引。 对于数字列中的给定值(例如 1),它可能与字符串列中的任意数量的值(例如“1”、“1”、“00001”或“01.e1”)进行比较。 这排除了对字符串列使用任何索引。

  • 查找特定索引列 key_col 的 MIN() 或 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,则按相反顺序读取键。 (或者,如果索引是降序索引,则按正向顺序读取键。)

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

    SELECT key_part3 FROM tbl_name
    WHERE key_part1=1
  • 对于小表或报表查询处理大部分或全部行的大表的查询,索引不太重要。 当查询需要访问大部分行时,按顺序读取比通过索引更快。 顺序读取最大限度地减少磁盘查找,即使查询不需要所有行。