between截断右侧字段,因其本质是闭区间范围查询(等价于>= and

联合索引中 BETWEEN 为什么截断右侧字段
BETWEEN 是典型的范围操作符,和 >、 一样,会破坏联合索引中“右侧字段”的有序性。B+ 树只在等值路径上保持后续列的全局有序;一旦进入 <code>a BETWEEN 10 AND 20 这类分支,b 和 c 就不再按统一顺序排列——比如 a=10 下的 b=5 可能紧挨着 a=19 下的 b=100,优化器无法用 b = 20 做索引内跳转。
怎么验证 BETWEEN 后字段真没走索引
别只看 EXPLAIN 的 key 字段是否显示索引名,重点盯两个指标:
-
key_len:对照索引定义算出各字段理论字节数(如INT是 4 字节,VARCHAR(50)在utf8mb4下最多 200 字节),反推实际用了几列。例如索引是(user_id, status, expire_time),查user_id = ? AND status = ? AND expire_time BETWEEN ? AND ?时若key_len = 8(刚好够前两列),说明expire_time没参与索引查找 -
Extra中是否出现Using where:如果该字段条件写在WHERE里却没进Using index,基本就是回表后逐行过滤了
BETWEEN 和 >=/ 的行为差异很小
很多人以为 >= 和 能“保留右侧字段”,其实只是优化器对边界处理稍友好些,但本质仍是范围条件。只要不是单点等值(如 <code>a = 10),而是跨区间(哪怕 a >= 10 AND a ),优化器仍可能放弃右侧字段——因为执行计划成本估算时,它更倾向把范围列放在最后。
-
a BETWEEN 10 AND 10等价于a = 10,右侧字段可继续生效 -
a BETWEEN 10 AND 11或a >= 10 AND a 都会切断 <code>b、c,行为一致 - 真正起作用的是“是否构成连续等值路径”,不是操作符写法本身
绕开 BETWEEN 失效的常见误区
试图用语法变形“骗过”优化器,多数只是增加复杂度,不解决根本问题:
- 把
expire_time BETWEEN '2026-01-01' AND '2026-01-31'拆成几十个OR expire_time = '2026-01-01' OR ...:SQL 过长,执行计划开销飙升,且OR容易触发全表扫描 - 用
UNION ALL拆多个等值查询:语义等价,但维护难、优化器可能拒绝合并,还容易引入临时表 -
FORCE INDEX:只强制选某索引,不改变 B+ 树内部遍历逻辑,右侧字段照样失效
唯一可靠的做法是让范围字段处于联合索引最右位置,并确保左侧全是高频等值条件——这个顺序不是“建议”,是 B+ 树结构决定的硬约束。











