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

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

联合索引能用上的查询条件长什么样?

只有满足「最左前缀匹配」的 WHERE 条件,才能真正走

INDEX(a, b, c)
这类联合索引。不是“包含这些字段就行”,而是必须从最左边开始、连续使用。

a = 1
✅ 走索引(只用 a)
a = 1 AND b = 2
✅ 走索引(a + b)
a = 1 AND b = 2 AND c = 3
✅ 走索引(全列匹配)
b = 2
❌ 不走索引(跳过了 a)
a = 1 AND c = 3
❌ 只用上 a,c 被跳过,b 没参与 →
b
字段无法利用索引排序,
c
实际失效
a IN (1,2) AND b = 3
✅ 走索引(
IN
算等值,仍满足最左前缀)

注意:MySQL 查询优化器会自动调整

WHERE
子句中字段顺序(比如把
b = 2 AND a = 1
改成
a = 1 AND b = 2
),但前提是所有字段都在同一层级且无函数/计算干扰 —— 别依赖它来“救场”,自己写对才是稳的。

联合索引字段顺序怎么排才不翻车?

顺序不是按字母或出现频率排,而是按「选择性」和「查询模式」定:高区分度字段放前面,高频过滤字段靠左,排序/分组字段尽量靠右。

错误示例:
INDEX(gender, age)
——
gender
只有男/女,索引树第一层就分裂成两支,后续
age
再怎么细分也意义不大
正确示例:
INDEX(age, gender)
—— 先按年龄精细切分,再在每个年龄段里筛性别,B+ 树搜索路径更短
如果常查
WHERE user_id = ? ORDER BY create_time DESC
,优先建
INDEX(user_id, create_time)
,而不是分开两个单列索引

验证选择性:可用

SELECT COUNT(DISTINCT col)/COUNT(*) FROM table
粗估;值越接近 1,该列越适合作为联合索引首列。

为什么加了联合索引,EXPLAIN 还显示 type=ALL 或 Using filesort?

EXPLAIN
type=ALL
表示全表扫描,
Extra: Using filesort
表示 MySQL 没法用索引完成排序 —— 这两类问题往往不是没建索引,而是索引没被“完整驱动”。

WHERE a = 1 ORDER BY b
+
INDEX(a, b)
✅ 能避免 filesort
WHERE a = 1 ORDER BY c
+
INDEX(a, b, c)
c
不在索引前缀连续段内,无法利用排序结构,仍 filesort
SELECT * FROM t WHERE b = 2
+
INDEX(a, b, c)
❌ 最左没匹配,直接退化为全表扫
WHERE a = 1 AND b > 10 ORDER BY c
+
INDEX(a, b, c)
⚠️
b
是范围查询,
c
的排序失效(B+ 树中,a 相同、b > 10 的 c 值是无序的)

关键点:范围查询(

>
,
, <code>BETWEEN
,
LIKE 'abc%'
)之后的字段,只能用于索引查找,不能用于排序或精确匹配。

什么时候该用联合索引,而不是多个单列索引?

当你的高频查询同时命中多个字段,且存在固定组合时,联合索引几乎总是优于多个单列索引 —— 因为 MySQL 一般一次只用一个索引(除非开启 index_merge,但代价高、不可控)。

SELECT * FROM orders WHERE user_id = 123 AND status = 'paid' AND created_at > '2025-01-01';
错:分别建
INDEX(user_id)
INDEX(status)
INDEX(created_at)
→ 优化器大概率只选一个,其余条件回表过滤,慢
对:建
INDEX(user_id, status, created_at)
→ 三条件一次性定位,且若只查这三列,还能覆盖索引(
Extra: Using index
更优:如果
status
只有 3–4 个值,而
user_id
是主键级区分度,就把
user_id
放最左;再根据实际数据分布微调

别忘了删冗余索引:比如已有

INDEX(a, b, c)
,再单独建
INDEX(a)
INDEX(a, b)
就是浪费 —— 写入开销白增,优化器还可能选错。

相关推荐