联合索引能代替单列索引吗?
不能一概而论。MySQL 的
WHERE条件中,只有当查询条件**从左到右连续匹配**联合索引的最左前缀时,索引才会被有效使用。比如联合索引
(a, b, c)可以加速
WHERE a = 1、
WHERE a = 1 AND b = 2、
WHERE a = 1 AND b = 2 AND c = 3,但对
WHERE b = 2或
WHERE c = 3完全无效。
所以如果你有高频查询
WHERE b = ?,单独建
(b)索引仍是必要的——联合索引
(a, b, c)并不“包含”对
b的独立查找能力。
什么时候该用联合索引而不是多个单列索引?
当多个字段**经常一起出现在 WHERE、ORDER BY 或 GROUP BY 中**,且顺序稳定时,联合索引更高效。MySQL 5.6+ 虽支持索引下推(ICP)和松散索引扫描,但多个单列索引在多条件查询中通常只能用上一个(选区分度最高的那个),其余条件回表后过滤,IO 开销大。
WHERE status = 'active' AND created_at > '2024-01-01'→ 建
(status, created_at)比两个单列索引更优
ORDER BY user_id, created_at DESC→ 联合索引可避免文件排序(
Using filesort) 单列索引过多会拖慢写入性能,每个 INSERT/UPDATE/DELETE 都要维护所有相关索引
联合索引字段顺序怎么排?
核心原则:**区分度高 + 经常用于等值查询的字段放左边,范围查询(
>,
BETWEEN,
LIKE 'abc%')字段放右边,排序/分组字段尽量靠右但不能打断最左前缀匹配。**
例如用户表常见查询:
WHERE tenant_id = ? AND status = ? AND created_at > ? ORDER BY id DESC。此时
(tenant_id, status, created_at)是合理顺序,因为:
tenant_id通常是租户隔离字段,等值且高区分度,适合做最左列
status也是等值,放在第二位可继续利用索引
created_at > ?是范围查询,它之后的字段(如
id)无法再用于索引查找,所以不建议把它放第三位后还指望
ORDER BY id走索引;若真需避免
filesort,可考虑
(tenant_id, status, created_at, id),但注意该索引体积更大
EXPLAIN 看不出联合索引是否生效?
关键看
key和
key_len字段:
key显示用了哪个索引 → 确认没走错索引
key_len表示实际用到索引的字节数 → 对比索引定义可反推用了几列。比如
utf8mb4字符串字段长度为 50,单列索引
key_len最大为
50 × 4 = 200;若联合索引
(a INT, b VARCHAR(50)),查
WHERE a = 1 AND b = 'x'时
key_len应为
4 + 200 = 204(INT 为 4 字节,VARCHAR 变长但等值匹配时按最大可能长度算) 如果
key_len明显偏小(比如只显示 4),说明只用到了联合索引第一列,后面条件没走索引
容易忽略的一点:
WHERE a = 1 OR b = 2这类条件,即使
a和
b各有单列索引,MySQL 也大概率不会合并使用(除非开启
index_merge且优化器认为划算),更别说联合索引了——这种场景往往需要重写逻辑或加冗余索引。
