mysql中的多列索引与单列索引的应用场景

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

什么时候该用多列索引而不是多个单列索引

MySQL 的优化器通常不会同时使用多个单列索引去加速同一个查询(除非启用了

index_merge
,但它是例外而非默认行为)。如果你常查
WHERE user_id = ? AND status = ?
,建两个单列索引
(user_id)
(status)
效果往往不如一个联合索引
(user_id, status)

关键看查询条件是否「左前缀匹配」:多列索引

(a, b, c)
能加速以下条件:

WHERE a = ?
WHERE a = ? AND b = ?
WHERE a = ? AND b = ? AND c = ?
WHERE a = ? AND b IN (?, ?) AND c = ?
(c 仍可用)

但无法加速

WHERE b = ?
WHERE b = ? AND c = ?
(缺少最左列
a
),此时索引失效。

单列索引更适合哪些场景

单列索引在以下情况更合适:

该列频繁单独出现在
WHERE
条件中,且值分布较均匀(如
email
order_no
作为外键字段,需保证引用完整性(如
user_id
在订单表中)
用于
ORDER BY col
GROUP BY col
,且不涉及其他过滤列
列基数极高(如 UUID),而组合后区分度没明显提升,建联合索引反而浪费空间

注意:如果已有单列索引

(a)
,又新建了多列索引
(a, b)
,那原来的
(a)
索引大概率可以删掉——因为
(a, b)
已能覆盖所有
a
单独查询的需求,还省下一次索引维护开销。

多列索引的列顺序怎么定

顺序不是随便写的,直接影响索引能否命中。核心原则是:「过滤性越强、越常用于等值查询的列放前面」。

比如用户表有

status
(只有 'active'/'inactive')、
created_at
(时间戳)、
user_id
(唯一):

WHERE status = 'active' AND user_id = 123
→ 推荐
(user_id, status)
,因为
user_id = ?
过滤性最强,能直接定位一行
WHERE created_at > '2024-01-01' AND status = 'active'
(status, created_at)
更好,因为
status
是等值,
created_at
是范围;MySQL 只能对多列索引中最左边的等值列之后的第一列用范围扫描

错误示例:

(created_at, status)
WHERE status = ?
完全无效;对
WHERE created_at > ? AND status = ?
也只能用上
created_at
status
变成表扫描过滤。

如何验证索引是否真的被用了

别猜,用

EXPLAIN
看执行计划:

EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 'paid';

重点关注这几列:

key
:显示实际使用的索引名
key_len
:值越大,说明用到的索引列越多(例如
key_len=8
可能只用了第一列,
key_len=12
表示前两列都参与了查找)
rows
:预估扫描行数,越小越好
Extra
:出现
Using index
表示覆盖索引;出现
Using where; Using index
是理想状态;若写的是
Using where; Using filesort
,说明
ORDER BY
没走索引

容易被忽略的一点:即使

EXPLAIN
显示用了索引,如果
rows
值接近全表行数,说明该索引选择性太差,可能还不如全表扫描——这时候得重新评估列顺序或是否真需要这个索引。

相关推荐