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 会为了保命而放弃精准探测,转而使用索引统计信息进行模糊预估。

  • 风险 :一旦估算错误,优化器可能会"脑抽"放着索引不用,跑去执行全表扫描
相关推荐
瀚高PG实验室44 分钟前
瀚高企业版V9.1.1在pg_restore还原备份文件时提示extract函数语法问题
数据库·瀚高数据库
TDengine (老段)1 小时前
TDengine Tag 设计哲学与 Schema 变更机制
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
敲个大西瓜1 小时前
Java项目常用数据归档方式
mysql
YOU OU2 小时前
Spring IoC&DI
java·数据库·spring
Muscleheng3 小时前
Navicat连接postgresql时出现‘datlastsysoid does not exist‘报错
数据库·postgresql
kyriewen3 小时前
面试官让我查各部门工资最高的员工,我用AI三秒写出窗口函数,他愣了
后端·mysql·面试
小码工作室3 小时前
使用 HAVING 进行 MySQL 集合筛选
mysql
罗超驿4 小时前
18.事务的隔离性和隔离级别:MySQL面试高频考点全解析
数据库·mysql·面试
jran-4 小时前
Redis 命令
数据库·redis·缓存
小江的记录本4 小时前
【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)
java·数据库·python·mysql·spring·面试·maven