索引用于快速找到具有特定列值的行。没有索引,MySQL 必须从第一行开始,然后读取整个表以找到相关行。表越大,这个成本越高。如果表具有相关列的索引,MySQL 可以快速确定数据文件中的位置,而不需要查看所有数据。这比顺序读取每一行要快得多。
大多数 MySQL 索引 (PRIMARY KEY、UNIQUE、INDEX 和 FULLTEXT) 都存储在 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 可以更高效地使用索引,如果它们被声明为相同的类型和大小。在这个上下文中,
VARCHAR和CHAR被认为是相同的大小。例如,VARCHAR(10)和CHAR(10)是相同的大小,但VARCHAR(10)和CHAR(15)不是。对于非二进制字符串列的比较,两个列都应该使用相同的字符集。例如,比较
utf8mb4列与latin1列将阻止使用索引。比较不同类型的列(例如比较字符串列与时间或数字列)可能会阻止使用索引,如果值不能直接比较而不需要转换。例如,对于数字列中的特定值
1,它可能与字符串列中的多个值相等,例如'1'、' 1'、'00001'或'01.e1'。这排除了字符串列的索引使用。 -
找到特定索引列
key_col的MIN()或MAX()值。这通过预处理器来优化,该预处理器检查您是否使用WHERE在所有 key 部分中,该部分出现在索引中的key_part_N=constantkey_col之前。在这种情况下,MySQL 对每个MIN()或MAX()表达式执行单个键查找,并将其替换为常量。如果所有表达式都被替换为常量,查询将立即返回。例如:SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10; -
如果对表进行排序或分组,并且排序或分组是基于可用索引的左most前缀(例如,
ORDER BY)。如果所有键部分都跟随key_part1,key_part2DESC,则键将以逆序读取。(或者,如果索引是降序索引,键将以正序读取。)请参阅 第 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 节,“避免全表扫描” 了解详情。