MySQL 中为什么我们要避免“多个范围查询”

一、 索引的"终结者":多个普通范围查询(>, <, BETWEEN)

这是最基础也最致命的坑。在联合索引 (a, b) 中,索引的威力在遇到第一个"范围"时就会发生截断

为什么会失效?

联合索引的底层是 B+ 树,它是按顺序排列的。

  • 等值查询 :如果 a = 1,那么在 a=1 的范围内,b 是绝对有序的。
  • 范围查询 :如果 a > 1,那么在命中的所有记录里,b 变成了局部有序、全局无序
后果:

MySQL 只能利用索引定位到 a 的范围,对于 b 字段,它无法在索引树上进行"跳跃查找",只能通过 Index Condition Pushdown (ICP) 逐条扫描过滤,甚至直接导致 Filesort(文件排序)


二、 索引的"幸存者":为什么多个 IN 条件能生效?

很多同学以为 IN 也是范围查询,其实在 MySQL 优化器眼里,IN 更像是一系列的等值点

为什么有效?

对于 WHERE a IN (1, 2) AND b IN (3, 4),MySQL 会将其拆解为 4 个精确的坐标点:

  1. (1, 3)
  2. (1, 4)
  3. (2, 3)
  4. (2, 4)

因为每一个组合都是确定的"点",MySQL 可以顺着 B+ 树的逻辑,精确地跳转到这 4 个位置。此时,ab 的索引都是生效的。


三、 深度思考:既然 IN 索引生效,为什么还要避免多个 IN?

既然 IN 不会截断索引,那是不是可以随便写?绝对不是。 多个 IN 会带来另一个恐怖的问题:组合爆炸与 Index Dive 成本

1. 笛卡尔积的诅咒

每一个 IN 列表的增加,都会让扫描路径呈指数级增长:

  • a IN (10个值) ×\times× b IN (10个值) ×\times× c IN (10个值) = 1000 条路径
2. Index Dive(索引下潜)的沉重代价

在 SQL 真正运行前,优化器需要计算成本。为了预估这 1000 条路径分别有多少行数据,它会执行 1000 次 Index Dive ------ 也就是 1000 次深入 B+ 树叶子节点的探测。

  • 编译开销:仅仅是生成执行计划,就可能消耗掉数百毫秒的 CPU。
  • 并发瓶颈:在高并发下,这种"探路"动作会瞬间耗尽数据库的线程资源。
3. 优化器的"背叛"

当组合数超过阈值(eq_range_index_dive_limit,通常是 200)时,MySQL 会为了保命而放弃精准探测,转而使用索引统计信息进行模糊预估。

  • 风险 :一旦估算错误,优化器可能会"脑抽"放着索引不用,跑去执行全表扫描
相关推荐
hashiqimiya6 小时前
postgres数据库操作指南
数据库
Bert.Cai6 小时前
MySQL MOD()函数详解
数据库·mysql
William Dawson6 小时前
【MySQL触发器超详细实战教程|从零基础到项目生产可用(避坑+案例+跨库+逗号拆分)】
数据库·mysql
.柒宇.6 小时前
AI 掘金头条项目-新闻模块实现
数据库·后端·python·fastapi
许彰午6 小时前
我手写了一个 Java 内存数据库(四):索引引擎、SQL 解析与总结
java·数据库·sql
若兰幽竹6 小时前
【HCIE-openGauss数据库认证】01 准备阶段:实验环境深度剖析与搭建指南
数据库·hcie-opengauss·华为专家级认证
杨云龙UP6 小时前
Oracle 19c多租户架构下设置用户密码永不过期及登录锁定策略说明_20260430
linux·运维·服务器·数据库·oracle
HackTorjan6 小时前
MySQL高可用架构设计与最佳实践
android·人工智能·mysql·adb·自动化
qiuyunoqy6 小时前
MySQL - 4 - mysqldump/mysqladmin/mysqlshow讲解
数据库·mysql