联合索引(也叫复合索引)是数据库调优里出现频率最高的概念之一,面试常问,生产环境也常踩坑。这篇把联合索引的核心机制一次讲透。
一、什么是联合索引
联合索引就是在多个列上建立的索引(如 KEY idx (a, b, c))。它和"给每个列单独建索引"完全不同:两个单列索引是两个独立结构,而联合索引是一个整体结构,按列顺序存储。
可以把它想象成电话簿:先按"姓"排序,同姓的再按"名"排序。你知道姓,电话簿很好用;知道姓和名,更好用;但只知道名不知道姓,电话簿就帮不上忙——这就是联合索引的精髓。
二、最左前缀原则(核心)
联合索引 (a, b, c) 只能支持以下组合命中索引:
aa, ba, b, c
不支持 b、c、b, c 这种跳过最左列的组合。
所以创建联合索引时,列的顺序就是一切:最常作为查询条件的列放最左,经常一起查询的列相邻排列。
三、索引的命中与失效场景
以下典型场景要注意:
能命中索引:
- where 条件覆盖索引最左列(如
where a = 1、where a = 1 and b = 2); - 查询列都在索引内(覆盖索引,避免回表);
- 范围查询左边的列仍可继续用索引。
索引失效的常见坑:
- where 条件里对索引列做了函数运算或隐式类型转换(如
where DATE(create_time) = '2026-01-01'); - 使用
!=、NOT IN、LIKE '%xx'这类无法利用索引的匹配; - 多表 join 时关联字段无索引或字符集不一致;
- 最左列缺失(前面说的跳过最左列)。
四、MySQL 怎么选索引:小心"走错索引"
当一个表有多条索引可走时,MySQL 根据查询成本选择。但联合索引的成本估算常以第一个字段为准,可能选错:
例如有 Index_1(Create_Time, Category_ID) 和 Index_2(Category_ID),当查询条件同时包含两个字段时,优化器可能优先走 Index_2(因为每个 category 的记录不多),反而更慢。
解决办法:根据查询模式调整字段顺序,用 EXPLAIN 观察实际走的索引,必要时用 FORCE INDEX 兜底,但最该做的是把索引设计成"贴合实际查询"的样子。
五、建索引的实战建议
- 加索引的字段要出现在 where 条件中,不在查询里的列建了也是浪费;
- 数据量少的表/字段不需要索引,全表扫描反而更快;
- where 条件里是 OR 关系时,索引常不起作用,考虑拆查询或用 UNION;
- 冗余索引要清理:已有
(a, b)再建(a)就是冗余,(b, a)则不是; - 建索引会占用磁盘空间、拖慢写入,不是越多越好,按实际高频查询设计。
创建方式:CREATE INDEX idx_name ON table_name (col1, col2);或 ALTER TABLE table_name ADD INDEX idx_name (col1, col2)。
写在最后
索引优化的本质是"让查询贴合索引结构":先梳理线上慢查询,确认高频条件组合,再设计联合索引的列顺序,最后用 EXPLAIN 验证。把这套流程跑熟,面试讲出原理,工作解决真实问题,都不在话下。
把联合索引这类高频考点当成面试练习的一部分,多讲几遍就自然了——需要的话可以在 可面猫笔试助手 里刷几组数据库的题,复习完直接检验掌握程度。