联合索引顺序错位直接导致索引失效
MySQL 的 B+ 树索引是严格按定义顺序逐列比较的,一旦 WHERE 条件跳过最左列(即“断层”),后续所有列都无法参与索引查找。比如建了
INDEX idx_user (city, age, status),但查询写成
WHERE age = 25 AND status = 'active',EXPLAIN 中
key字段会显示
NULL,
type是
ALL,
rows接近全表行数——本质就是退化为全表扫描。 不是“部分生效”,而是整个联合索引基本不被使用 即使只漏掉第一个字段,优化器也无法定位起始叶子节点,B+ 树失去有序遍历基础 ORDER BY 或 GROUP BY 的列顺序/方向若与索引不一致,也会触发
Using filesort,哪怕 WHERE 已命中索引
哪些查询能真正用上联合索引
只有满足“最左前缀 + 连续等值 + 范围靠后”三要素,索引才能高效工作。以
INDEX idx_log (app_id, event_type, created_at)为例:
WHERE app_id = 100→ 用第 1 列
WHERE app_id = 100 AND event_type IN ('click', 'submit') → 用前 2 列(IN 视为等值集合)
WHERE app_id = 100 AND event_type = 'click' AND created_at > '2024-01-01'→ 全部 3 列参与,但注意:
created_at是范围条件,它右侧不能再有用于查找的列(不过仍可做 ICP 过滤)
WHERE app_id > 100 AND event_type = 'click'→
event_type只能做索引条件下推(ICP),不能用于快速定位
索引列顺序怎么排才合理
顺序不是按字段名字母排,也不是按建表顺序堆砌,核心逻辑是:高频等值过滤列优先,高区分度列靠左,范围列放最后。
错误示范:INDEX (status, region, created_at)——
status只有 'active'/'inactive',基数太低,作为首列筛选后仍剩大量数据,索引效率差 正确思路:先看 WHERE 中哪些条件几乎每次都出现(如
user_id、
tenant_id),再看哪个字段值越分散越好(如
created_at比
status更适合前置) 如果某列常用于 ORDER BY,且方向固定(如
score DESC),它应紧接在等值列之后,并与索引定义方向一致,否则排序无法复用索引
如何验证和修复索引顺序问题
别猜,用
EXPLAIN看真实执行路径;别忍,该重建就重建——联合索引顺序改了必须
DROP再
CREATE,ALTER 不支持重排。 检查命令:
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'paid';,重点盯
key是否非空、
rows是否明显小于总行数 发现失效后,先确认查询模式是否稳定:如果
WHERE status = ?是高频独立查询,那原联合索引设计本身就有缺陷,得补单列索引或重构联合索引 重建索引前,用
ANALYZE TABLE orders;更新统计信息,避免优化器因旧数据误判
索引顺序一旦定错,不是性能打七折八折,而是从“毫秒级响应”滑向“秒级甚至超时”。最容易被忽略的是:开发阶段数据量小,问题不暴露;上线后数据增长十倍,原来能跑的 SQL 突然变慢——这时候再查,往往第一反应是加机器,而不是翻出那条早该重写的
CREATE INDEX语句。
