联合索引中,>导致右侧列索引失效而>=可保留右侧列索引,根本原因是b+树结构下>=提供等值锚点使右侧列保持局部有序,>则破坏有序性;同时>=加锁更精准,降低死锁风险。

> 和 会让联合索引“断在右边”,这是 MySQL 索引最常被误用的点之一。
MySQL 的联合索引是按定义顺序逐列排序的,一旦某列用了 <code>> 或 ,优化器就无法继续用右侧列的索引值做等值定位——因为范围扫描会跳过右侧列的有序性,导致它直接失效。
<h3>联合索引中 <code>> / 导致右侧列索引失效
比如有联合索引 (a, b, c):
-
WHERE a = 1 AND b > 10 AND c = 'x'→c列不走索引(EXPLAIN中key_len显示只用到前两列) -
WHERE a = 1 AND b >= 10 AND c = 'x'→c列可以走索引(key_len包含全部三列)
根本原因不是语法问题,而是 B+ 树结构决定的:当 b > 10 时,匹配的 b 值可能对应多个 c 值,且这些 c 在物理上不连续,无法利用索引有序性快速定位 c = 'x'。
BETWEEN 和 >=/ 的行为差异
BETWEEN low AND high 等价于 col >= low AND col ,它本身不会导致右侧列失效——但前提是左侧列没被 <code>>/ 截断。
-
WHERE a = 1 AND b BETWEEN 10 AND 20 AND c = 'x'→c可走索引 -
WHERE a > 1 AND b = 10 AND c = 'x'→b和c都不走索引(a是范围,后面全废)
注意:BETWEEN 对单列有效,但它不能“修复”已被前面 > 打断的联合索引链。
为什么 >= 能保留右侧索引而 > 不能?
这不是 MySQL 故意区别对待,而是优化器对“等值起点”的识别能力不同:
-
b >= 10:优化器知道从第一个b = 10的索引项开始扫描,此时c的值仍保持局部有序,可继续下推 -
b > 10:没有明确的b等值锚点,必须跳到第一个b > 10的位置,这个位置的c分布完全不可预测
实测中,key_len 差 5 字节(比如从 49 变成 54),往往就是 c 列是否参与索引查找的分水岭。
容易被忽略的锁行为影响
范围查询不只是性能问题,还直接影响加锁范围:
-
WHERE id > 100(聚集索引)→ 加Next-key Lock,锁住匹配记录 + 后续间隙,甚至包括supremum伪记录 -
WHERE id >= 100→ 对id = 100的行加Record Lock,其余仍为Next-key Lock
这意味着,仅改一个符号(> → >=),在高并发更新场景下,死锁概率、锁等待时间都可能明显变化——这点在线上排查时经常被漏掉。
>= 就别用 >,哪怕语义上多包含一个边界值,也比索引失效+锁扩大更可控。真正的难点不在写法,而在意识到:**索引是否生效,取决于整个 WHERE 条件中所有操作符的组合方式,而不是单看某一个字段。**











