组合索引生效的关键是匹配查询模式、遵守最左前缀原则、控制范围查询位置;单列索引无法自动拼接优化and查询,因b+树结构决定其彼此无序关联。

直接说结论:组合索引不是把WHERE里出现的字段堆一起就行,顺序错了,90%的查询压根不走索引。真正起效的关键是匹配查询模式 + 遵守最左前缀 + 控制范围查询位置。
为什么多个单列索引在AND查询中基本没用
MySQL不会自动拼接多个单列索引去加速 WHERE a = 1 AND b = 2 AND c > '2024-01-01' 这类查询。它可能:
- 只选其中一个索引(比如
a),然后对结果集逐行判断b和c条件 → 回表成本高 - 退而求其次启用
index_merge_intersection→ 要读多次索引、做内存交集、常触发临时表,性能差且不稳定 - 干脆全表扫描(
EXPLAIN显示type=ALL或key=NULL)
这不是配置问题,是B+树结构决定的:单列索引各自有序,但彼此之间无序关联。
复合索引字段顺序怎么排才真正生效
顺序不是按表结构来,也不是按字母或“区分度高低”拍脑袋定,而是严格对齐高频查询的实际使用模式:
-
user_id和tenant_id几乎每次查询都带=?那就放最左,哪怕status唯一值更少 - 经常查
WHERE status = ? AND created_at > ??索引必须是(status, created_at),反过来就废了 -
IN是等值,不是范围:WHERE a IN (1,2,3) AND b = 5能用上(a, b)全部两列 -
LIKE 'abc%'算前缀匹配,能用索引;LIKE '%abc'或LIKE '%abc%'直接跳过整个索引
记住:范围查询(>、、<code>BETWEEN、LIKE 'xxx%')是分水岭,它右边的列无法参与 WHERE 过滤,最多用于 ORDER BY 或覆盖。
怎么验证组合索引真被用了,而不是假阳性
别只看 EXPLAIN 里 key 有值就以为万事大吉。盯死三个字段:
-
key为空 → 没走索引(检查是否漏了最左字段、是否对列用了函数如YEAR(created_at)) -
key_len= 8(假设INT占4字节)→ 实际只用了前两个字段,第三个没命中 -
Extra里出现Using index才算真正覆盖;Using index condition表示用了ICP,但仍有回表;Using where; Using index是常见误导项,只说明WHERE用了索引,不代表覆盖
如果 rows 接近全表行数,说明索引建了但没起效——可能是选择性太差(比如只有2个值的 is_deleted 单独作首列),也可能是条件没对齐最左前缀。
ORDER BY 和 SELECT 字段要不要塞进组合索引
要,但不是随便加:
-
ORDER BY字段必须紧接在等值条件之后,且方向一致(MySQL 5.7 要求全升序或全降序;8.0+ 支持混合方向,但得显式声明) - 比如
WHERE category = 'A' ORDER BY created_at DESC,索引应为(category, created_at),不能是(created_at, category) -
SELECT里只查索引列?加到索引末尾就是覆盖索引,避免回表;如果还要查amount、order_no,就把它们追加在最后 - 但别无脑堆字段:写入负担随索引宽度线性增长,
INSERT/UPDATE变慢,存储翻倍
最易被忽略的一点:即使索引结构和查询看起来严丝合缝,只要在索引列上用了函数(WHERE DATE(created_at) = '2024-01-01')、隐式类型转换(WHERE user_id = '123' 但 user_id 是 INT)、或者字符集不匹配,索引就静默失效。











