MySQL范围查询能用上索引,但有明确的限制规则——不是所有带
>、
、<code>BETWEEN或
LIKE 'abc%'的查询都能走索引,关键看它在复合索引中的位置和后续字段是否还能被利用。
范围查询会“截断”复合索引
复合索引遵循最左前缀原则,而范围查询是其中的分水岭:一旦某个字段用了范围条件,它右边的所有字段就无法再用于索引查找(但仍可能参与过滤或覆盖)。
索引(a, b, c),查询
WHERE a = 1 AND b > 10 AND c = 5:只有
a和
b参与索引查找,
c = 5不会加速定位,只能在满足
b > 10的结果集里逐行判断。 同个索引下,
WHERE a > 1 AND b = 2:仅
a有效,
b完全不走索引查找,因为范围出现在最左列,后续列全部失效。
等值 + 范围 + 等值?后一个等值不生效
很多人误以为“只要字段在索引里,就能用上”,其实顺序和类型决定一切。复合索引中,必须先完成所有等值匹配,才能进入范围扫描;范围之后的字段,哪怕写在 WHERE 里,也不参与索引驱动。
索引(status, create_time, user_id),查询
WHERE status = 'failed' AND create_time > '2025-01-01' AND user_id = 123:索引只用到
create_time,
user_id = 123是在范围扫描出的若干行中做内存过滤,不是索引查找。 若把索引改为
(status, user_id, create_time),同样查
status = 'failed' AND user_id = 123 AND create_time > '2025-01-01':此时
status和
user_id先做等值定位,再对
create_time做范围扫描,效率更高。
LIKE 使用索引也有前提
LIKE是否走索引,取决于通配符位置:
LIKE 'abc%':可以走索引(前缀匹配,相当于范围:
≥ 'abc'且
)。
LIKE '%abc'或
LIKE '%abc%':无法使用 B+Tree 索引,只能全表扫描(除非用全文索引)。
LIKE 'abc_'(单下划线):仍属于前缀匹配,可走索引。
范围字段本身要避免函数或运算
即使字段有索引,只要在 WHERE 中对它做了计算或调用函数,索引就会失效:
❌WHERE DATE(create_time) = '2025-12-01'→ 函数导致索引失效。 ✅
WHERE create_time >= '2025-12-01' AND create_time → 直接比较,可走索引。❌
WHERE price * 1.1 > 100→ 运算导致失效。 ✅
WHERE price > 100 / 1.1→ 把计算移到右侧,保持左侧为纯列引用。
