mysql索引顺序对查询性能有影响吗_mysql索引设计注意事项

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

索引列顺序直接影响
WHERE
条件能否命中索引

MySQL 使用 B+ 树索引,数据按索引定义的列顺序物理排序。如果查询条件没用上最左前缀,后续列就无法利用索引下推或范围扫描。比如有复合索引

INDEX (a, b, c)

WHERE a = 1 AND b = 2
→ 可用全部两列做等值查找
WHERE a = 1 AND c = 3
→ 仅能使用
a
c
被跳过(
b
缺失导致断层)
WHERE b = 2 AND c = 3
→ 完全无法使用该索引

本质是 B+ 树层级结构决定的:第一层按

a
排序,第二层才在每个
a
值内按
b
排序,没有
a
就找不到入口。

范围查询后列无法用于索引过滤

一旦某列出现范围操作(

>
、<code>BETWEEN
LIKE
前缀通配除外),其右侧所有列都只能用于回表,不能参与索引查找或
WHERE
下推。

INDEX (a, b, c)
,查询
WHERE a = 1 AND b > 2 AND c = 3
c = 3
不会走索引过滤,只靠回表后判断
若把顺序改成
INDEX (a, c, b)
,同样无法让
c
b > 2
后生效

所以要把高选择性且常用于等值查询的列放左边,范围列尽量靠右;避免把

created_at > '2024-01-01'
这类放在中间位置。

ORDER BY
GROUP BY
必须匹配索引最左前缀才能避免 filesort

MySQL 仅当

ORDER BY
列完全对应索引最左连续列,且排序方向一致(全
ASC
或全
DESC
),才能直接利用索引有序性。例如:

INDEX (user_id, status, created_at)
SELECT * FROM t WHERE user_id = 123 ORDER BY status, created_at
→ 无 filesort
SELECT * FROM t WHERE user_id = 123 ORDER BY created_at
→ 仍需 filesort(跳过了
status
SELECT * FROM t WHERE user_id = 123 ORDER BY status DESC, created_at ASC
→ filesort(混合方向)

注意:8.0+ 支持降序索引,但老版本遇到混合排序基本只能靠覆盖索引或调整查询逻辑绕开。

区分度高的列优先,但别忽略查询模式本身

高区分度(如

user_id
)通常适合放左边,但实际要结合
WHERE
组合频次看:

如果 90% 查询都是
WHERE tenant_id = ? AND status = ?
,哪怕
tenant_id
区分度低,也应放最左(因为必须用它过滤租户隔离)
WHERE a IN (?, ?, ?) AND b = ?
a
是多值等值,
b
是单值等值,优先把
b
放左更利于精确查找(IN 在某些场景下可走 range)
避免把
is_deleted TINYINT
放最左——即使加了索引,优化器大概率因选择率太低而拒用

真正关键的是「哪些列总是一起出现、是否常被用于等值、有没有范围、是否承担排序/分组」——不是单纯看 cardinality 数值。

相关推荐