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 个位置。此时,a 和 b 的索引都是生效的。


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

  • 风险 :一旦估算错误,优化器可能会"脑抽"放着索引不用,跑去执行全表扫描。
相关推荐
IvorySQL3 小时前
PostgreSQL 日报|修复截断 zstd 备份检测(10 月 9 日)
数据库·postgresql
刘胡子大叔3 小时前
SQL 脚本的导入顺序
数据库·sql
代码什么用3 小时前
Spring对IoC的实现
数据库·spring
hz567896 小时前
涉密视频会议设备配置指南:终端、音视频采集与配套设施选型
服务器·网络·数据库·安全·实时音视频·信息与通信·智能硬件
广州浮点FLOATLIC6 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
程序员Sunday6 小时前
MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来
数据库·mysql
半杯咖啡半行码6 小时前
Qt开发实战:数据库、MV 模式、QProcess与串口通信全攻略
数据库·qt
Yyyyyy~6 小时前
[ Mysql ] 库的操作
mysql
小米里的大麦6 小时前
16 MySQL 事务
数据库·mysql
西柚小萌新6 小时前
【LLM&&AI应用开发 八股文】--4.3.Agent智能体(下)
java·开发语言·数据库