MySQL 联合索引实战指南:最左前缀、命中规则与调优

联合索引(复合索引)是 MySQL 性能调优的核心。本文讲透联合索引的底层原理、最左前缀原则、索引选择与失效场景,附建索引的实战建议,帮助后端开发者写出更高效的 SQL。

联合索引(也叫复合索引)是数据库调优里出现频率最高的概念之一,面试常问,生产环境也常踩坑。这篇把联合索引的核心机制一次讲透。

一、什么是联合索引

联合索引就是在多个列上建立的索引(如 KEY idx (a, b, c))。它和"给每个列单独建索引"完全不同:两个单列索引是两个独立结构,而联合索引是一个整体结构,按列顺序存储。

可以把它想象成电话簿:先按"姓"排序,同姓的再按"名"排序。你知道姓,电话簿很好用;知道姓和名,更好用;但只知道名不知道姓,电话簿就帮不上忙——这就是联合索引的精髓。

二、最左前缀原则(核心)

联合索引 (a, b, c) 只能支持以下组合命中索引:

  • a
  • a, b
  • a, b, c

不支持 bcb, c 这种跳过最左列的组合。

所以创建联合索引时,列的顺序就是一切:最常作为查询条件的列放最左,经常一起查询的列相邻排列。

三、索引的命中与失效场景

以下典型场景要注意:

能命中索引

  • where 条件覆盖索引最左列(如 where a = 1where a = 1 and b = 2);
  • 查询列都在索引内(覆盖索引,避免回表);
  • 范围查询左边的列仍可继续用索引。

索引失效的常见坑

  • where 条件里对索引列做了函数运算或隐式类型转换(如 where DATE(create_time) = '2026-01-01');
  • 使用 !=NOT INLIKE '%xx' 这类无法利用索引的匹配;
  • 多表 join 时关联字段无索引或字符集不一致;
  • 最左列缺失(前面说的跳过最左列)。

四、MySQL 怎么选索引:小心"走错索引"

当一个表有多条索引可走时,MySQL 根据查询成本选择。但联合索引的成本估算常以第一个字段为准,可能选错:

例如有 Index_1(Create_Time, Category_ID)Index_2(Category_ID),当查询条件同时包含两个字段时,优化器可能优先走 Index_2(因为每个 category 的记录不多),反而更慢。

解决办法:根据查询模式调整字段顺序,用 EXPLAIN 观察实际走的索引,必要时用 FORCE INDEX 兜底,但最该做的是把索引设计成"贴合实际查询"的样子。

五、建索引的实战建议

  1. 加索引的字段要出现在 where 条件中,不在查询里的列建了也是浪费;
  2. 数据量少的表/字段不需要索引,全表扫描反而更快;
  3. where 条件里是 OR 关系时,索引常不起作用,考虑拆查询或用 UNION;
  4. 冗余索引要清理:已有 (a, b) 再建 (a) 就是冗余,(b, a) 则不是;
  5. 建索引会占用磁盘空间、拖慢写入,不是越多越好,按实际高频查询设计。

创建方式:CREATE INDEX idx_name ON table_name (col1, col2);或 ALTER TABLE table_name ADD INDEX idx_name (col1, col2)

写在最后

索引优化的本质是"让查询贴合索引结构":先梳理线上慢查询,确认高频条件组合,再设计联合索引的列顺序,最后用 EXPLAIN 验证。把这套流程跑熟,面试讲出原理,工作解决真实问题,都不在话下。

把联合索引这类高频考点当成面试练习的一部分,多讲几遍就自然了——需要的话可以在 可面猫笔试助手 里刷几组数据库的题,复习完直接检验掌握程度。