mysql联合索引怎么用_mysql索引规则解析

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

联合索引到底能不能用上,只看最左字段有没有被等值过滤

MySQL 不会因为你写了

b = 2 AND a = 1
就自动“倒着走”索引。它只认最左边那个字段是否出现在查询条件中、且是等值(或
IN
)匹配。
只要
a
没出现在 WHERE 条件里,哪怕你建的是
INDEX(a, b, c)
,这条语句就直接退化为全表扫描:
SELECT * FROM t WHERE b = 2
type=ALL
key=NULL

✅ 正确写法:
WHERE a = 1
WHERE a = 1 AND b > 10
WHERE a IN (1,2,3) AND b = 5
❌ 错误写法:
WHERE b = 2
WHERE c = 3
WHERE b = 2 AND c = 4
⚠️ 注意:
WHERE a = 1 AND c = 3
只能用上
a
c
完全无效 —— 中间跳过了
b
,后续字段全部失效

ORDER BY 能不能走索引,取决于排序字段是否在最左前缀连续段内

联合索引不是“包含这些字段就能排序”,而是要求:排序字段必须紧接在过滤字段之后,中间不能断档,也不能被范围查询截断。
比如有

INDEX(user_id, create_time)

WHERE user_id = 123 ORDER BY create_time DESC
✅ 无 filesort
WHERE user_id > 100 ORDER BY create_time DESC
user_id
是范围,
create_time
失效,必 filesort

✅ 能避免
Using filesort
WHERE a = 1 ORDER BY b
WHERE a = 1 AND b = 2 ORDER BY c
❌ 必然触发
Using filesort
WHERE a = 1 ORDER BY c
(跳过
b
)、
WHERE a = 1 AND b > 10 ORDER BY c
b
是范围,
c
无序)
? 小技巧:如果常查
WHERE status = ? ORDER BY updated_at
,优先建
INDEX(status, updated_at)
,别指望两个单列索引拼起来能排序

字段顺序怎么排?别按字母,要按区分度 + 查询模式

高区分度字段放最左,不是为了“好看”,是为了让 B+ 树第一层就能切掉最多数据。
比如

gender
只有男/女,建
INDEX(gender, age)
相当于先分两桶,再每桶里筛年龄 —— 第一层几乎没过滤能力;反过来建
INDEX(age, gender)
,先按年龄切成几十段,再每段里筛性别,效率高得多。

? 验证选择性:
SELECT COUNT(DISTINCT col)/COUNT(*) FROM table
,越接近 1 越好
? 查看高频查询:如果 80% 的查询都带
WHERE tenant_id = ?
,那
tenant_id
就该放最左,哪怕它区分度不如
id
? 避免默认值为
NULL
:联合索引中任意一列含
NULL
,该行就不进索引 —— 设计表时尽量用
NOT NULL DEFAULT ''
0

EXPLAIN 显示 type=ALL 或 Using filesort,八成是索引没被“完整驱动”

别急着加索引,先看

EXPLAIN
key
key_len
字段:
如果
key
是你的联合索引名,但
key_len
很小(比如预期 12,实际只有 4),说明只用了第一个字段;
如果
key=NULL
,那连最左字段都没命中,索引等于白建。

? 实操建议:用
SHOW INDEX FROM table_name
确认索引字段顺序和长度
? 测试时别只跑单条 SQL:用真实业务参数,比如
WHERE a = 1 AND b = 2
在测试数据里可能命中,但线上
a = 1
占比 95%,那就几乎不走
b
⚠️ 最容易被忽略的一点:
OR
条件会让整个联合索引失效,除非每个
OR
分支都有独立索引 —— 别试图靠
INDEX(a,b)
支持
WHERE a = 1 OR b = 2

相关推荐