★ 最左前缀原则是什么?哪些常见写法会导致索引失效?
结论先行:联合索引 (a, b, c) 按“从左到右连续匹配”生效:必须从最左列 a 开始且中间不断档,遇到范围查询(>、<、between)后其右边列失效;对列做函数/运算、隐式类型转换、前导通配符等写法则会让索引根本走不上。
一、最左前缀的三种用法
| 查询条件 | 能否用上 (a,b,c) | 说明 |
|---|---|---|
| a = 1 | 用 a | 最左列命中 |
| a = 1 AND b = 2 | 用 a,b | 连续前缀 |
| a = 1 AND b = 2 AND c = 3 | 用 a,b,c | 全命中,最优 |
| b = 2 AND c = 3 | 失效 | 没从 a 开始 |
| a = 1 AND c = 3 | 只用 a | b 断档,c 用不上 |
| a > 1 AND b = 2 | 只用 a | 范围之后 b 失效 |
-- 正确姿势:范围列放最后
CREATE INDEX idx_ab ON t (a, b); -- a 做等值,b 做范围
SELECT * FROM t WHERE a = 1 AND b > 5; -- a、b 都用上
二、让索引失效的常见写法
- 对索引列使用函数或表达式:WHERE YEAR(create_time) = 2024、WHERE id + 1 = 5。
- 隐式类型转换:字符串列与数字比较,或 varchar 字段接数值条件。
- LIKE 前导通配:WHERE name LIKE '%xx';尾部通配 'xx%' 则可用。
- OR 连接非索引列:一个分支走不了索引,整个条件往往退化为全表扫。
- join 两侧字符集/排序规则不一致,导致索引列隐式转换失效。
- 优化器选择:回表成本高于全表扫描时,有索引也可能弃用(可用 FORCE INDEX 验证)。
- 不等于与 NOT 前缀:!=、NOT IN、NOT LIKE 通常让优化器选择全表扫描(覆盖索引场景例外)。
三、一句口诀
等值在最前,范围放最后;前缀别断档,函数类型绕道走。
常见追问与记忆点
- 追问:a = 1 AND b > 2 AND c = 3 会用到哪些列?只用 a、b(范围后 c 失效),建议把 c 调到 b 前面。
- 追问:怎么确认走没走索引?EXPLAIN 看 key 与 Extra,见第 29 章。
- 记忆点:最左前缀是“从最左开始且连续匹配”;失效本质是优化器无法按索引顺序定位的写法。