mysql范围查询如何使用索引_mysql范围查询索引规则

MySQL范围查询能否用索引取决于复合索引中字段顺序与条件类型:等值条件须在范围条件左侧,范围后字段仅能过滤不能查找;LIKE需前缀匹配(如'abc%')才走索引;对索引字段做函数或运算将导致失效。

MySQL范围查询能用上索引,但有明确的限制规则——不是所有带>BETWEENLIKE 'abc%'的查询都能走索引,关键看它在复合索引中的位置和后续字段是否还能被利用。

范围查询会“截断”复合索引

复合索引遵循最左前缀原则,而范围查询是其中的分水岭:一旦某个字段用了范围条件,它右边的所有字段就无法再用于索引查找(但仍可能参与过滤或覆盖)。

  • 索引 (a, b, c),查询 WHERE a = 1 AND b > 10 AND c = 5:只有 ab 参与索引查找,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_timeuser_id = 123 是在范围扫描出的若干行中做内存过滤,不是索引查找。
  • 若把索引改为 (status, user_id, create_time),同样查 status = 'failed' AND user_id = 123 AND create_time > '2025-01-01':此时 statususer_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 → 把计算移到右侧,保持左侧为纯列引用。