mysql中联合索引与单列索引的选择

来源:这里教程网 时间:2026-02-28 20:45:00 作者:

联合索引能代替单列索引吗?

不能一概而论。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
且优化器认为划算),更别说联合索引了——这种场景往往需要重写逻辑或加冗余索引。

相关推荐