联合索引列顺序需遵循最左前缀匹配原则,高频高选择性列优先放左,等值查询列靠前,范围查询列靠后,排序分组字段可追加末尾,覆盖索引可避免回表,但需避免隐式转换和函数导致失效。

联合索引的列顺序不是随便排的,它直接决定索引能否被用上、能用上多少。核心原则是:**最左前缀匹配**——查询条件必须从索引最左边的列开始连续匹配,中间不能跳过。
按查询频率和选择性排顺序
高频、高区分度(选择性好)的列优先放左边。比如用户表中 status 只有“启用/禁用”两个值,而 user_id 唯一,那 user_id 就比 status 更适合放索引左侧。
- 等值查询列(
=或IN)可放前面,它们对顺序不敏感,但影响后续范围查询是否生效 - 范围查询列(
>、、BETWEEN、LIKE 'abc%')尽量靠后,一旦出现,其右边的列就无法走索引了 - 排序(
ORDER BY)和分组(GROUP BY)字段,如果和查询条件列一致,可顺势纳入索引末尾,避免额外排序
看实际 WHERE 条件怎么写
索引要为最常出现的 WHERE 组合服务。比如经常查 WHERE city = ? AND age > ?,那就建 (city, age);若还常查 WHERE city = ? AND status = ? AND create_time > ?,且 status 也是等值,可扩展为 (city, status, create_time)。
- 单独查
age > 25不会用到(city, age)索引,因为没用上最左列 -
WHERE status = ? AND city = ?能用(city, status),MySQL 优化器会自动调整顺序匹配最左前缀 -
WHERE city = ? AND age > ? ORDER BY name,若想避免 filesort,索引可设为(city, age, name)
覆盖索引顺便优化
如果查询只涉及几列,把它们全包含进联合索引里,就能实现“索引覆盖”,不用回表查数据行,速度更快。
- 例如
SELECT user_id, name, email FROM users WHERE dept_id = ? AND is_active = ?,可建索引(dept_id, is_active, user_id, name, email) - 注意:宽索引会增加写入开销和内存占用,别无脑堆字段,只加真正需要的
- 用
EXPLAIN看Extra列是否出现Using index,确认是否命中覆盖
别忽略隐式类型转换和函数操作
哪怕索引列顺序完美,只要 WHERE 里对索引列用了函数或隐式转换,索引就失效。
- 错:
WHERE YEAR(create_time) = 2024→ 改成create_time >= '2024-01-01' AND create_time - 错:
WHERE mobile = 13812345678(mobile 是字符串类型)→ 改成'13812345678' - 错:
WHERE name LIKE '%张%'→ 左模糊无法走索引,考虑全文索引或业务规避
索引列序本质是和查询模式对齐的过程,没有银弹,只有结合慢查日志、执行计划和业务场景反复验证。建完记得用 EXPLAIN 看一眼 key_len 和 type,比凭感觉靠谱得多。










