首页 >> 基础教程

mysql索引最左匹配原则

         在 MySQL 中,最左前缀原则(Leftmost Prefix Principle)是针对复合索引(多列索引)如何被查询优化器有效使用的核心规则。理解这个原则对于设计高效的索引和编写优化查询至关重要。

核心定义:

一个复合索引 INDEX (col1, col2, col3, ...) 在磁盘上存储时,是按照索引定义中列的顺序从左到右进行排序的。最左前缀原则规定:

查询的 WHERE 子句或 JOIN 条件中,必须包含复合索引的最左边的一个或多个列,并且这些列在查询条件中出现的顺序必须与索引定义中的顺序一致(可以跳过右边的列,但不能跳过左边的列),MySQL 才能有效地利用这个复合索引。

关键点解释:

  1. 必须从最左列开始: 查询条件中必须包含索引定义中的第一列(col1)。如果查询条件中没有 col1,即使包含了 col2col3 等,MySQL 通常也无法使用这个复合索引进行高效查找(可能会进行全表扫描或只使用部分后续列的索引,但效率远不如使用最左列)。

  2. 顺序一致(可跳过右边列):

    1. 查询条件中的列顺序不需要严格和索引定义的列顺序完全相同(比如 WHERE col1 = ... AND col3 = ...)。

    2. 但是,被使用的列在索引定义中的顺序必须是连续的,并且从最左边开始。你可以理解为只能使用索引定义中列的一个前缀子集

    3. 例子:索引 (A, B, C)

      1. WHERE A = ? (使用 A)

      2. WHERE A = ? AND B = ?  (使用 A, B)

      3. WHERE A = ? AND C = ? (使用 AC 无法直接利用索引定位,但 A 可以缩小扫描范围,C 可能作为过滤条件在索引扫描后应用)

      4. WHERE B = ? (缺少最左列 A,无法使用索引)

      5. WHERE B = ? AND C = ? (缺少最左列 A,无法使用索引)

      6. WHERE A = ? AND B > ? AND C = ? (使用 A, B 进行查找和范围扫描,C 在 B 的范围扫描结果内作为过滤条件。范围查询 B > ? 之后的列 C 无法再用于索引查找,只能过滤)

  3. 范围查询的影响: 如果查询条件中对索引中的某一列使用了范围查询(如 ><BETWEENLIKE 'prefix%'),那么:

    1. 该列本身及其左边的列仍然可以用于索引查找。

    2. 该列右边的所有列将无法再用于索引查找(即无法再缩小扫描范围),它们只能在扫描到符合范围条件的行之后,作为额外的过滤条件(Using where)来应用。

    3. 例子:索引 (A, B, C)

      1. WHERE A = 10 AND B > 20 AND C = 30

        1. A=10 用于精确查找。

        2. B>20 用于范围扫描。

        3. C=30 无法再用于索引查找定位,只能在扫描到的 A=10 AND B>20 的结果集中,对每一行检查 C=30 是否为真(Using where)。

  4. 覆盖索引: 最左前缀原则不仅适用于 WHERE 子句,也适用于 ORDER BY 和 GROUP BY 子句。更重要的是,如果一个查询只需要访问索引中包含的列(即索引“覆盖”了查询所需的所有列),那么即使它只使用了索引的最左前缀部分,MySQL 也只需扫描索引本身而无需回表查询数据行,这可以极大提升性能(Extra: Using index)。

为什么有这个原则?

这与 B+Tree 索引的物理存储结构有关。复合索引 (A, B, C) 在 B+Tree 中是先按 A 排序,在 A 相同的情况下按 B 排序,在 A 和 B 都相同的情况下才按 C 排序。如果没有最左边的列 A,数据库就不知道从索引树的哪个分支开始查找,相当于失去了有序性,只能退回到低效的全表扫描。

总结与最佳实践:

  1. 设计索引: 创建复合索引时,仔细考虑列的顺序。将最常用于等值查询区分度高(唯一值多)的列放在左边。将用于范围查询或排序的列放在等值查询列之后,或者考虑单独为它们建索引。

  2. 编写查询: 确保你的 WHERE / JOIN / ORDER BY / GROUP BY 子句能够利用到复合索引的最左前缀。如果查询条件无法包含最左列,考虑为该查询单独创建一个不同的索引。

  3. 利用覆盖索引: 尽量让查询只选择索引列,避免 SELECT *,这样即使查询只用了索引的一部分,也可能通过覆盖索引获得高性能。

  4. 使用 EXPLAIN 在 SQL 语句前加上 EXPLAIN,查看 MySQL 的执行计划。关注 possible_keys(可能使用的索引)、key(实际使用的索引)、key_len(使用的索引长度,反映了使用了索引的多少前缀列)以及 Extra 列(如 Using index 表示覆盖索引,Using where 表示索引扫描后进行了过滤)。这是验证查询是否有效利用最左前缀原则的最直接方法。




最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1