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

  • 风险 :一旦估算错误,优化器可能会"脑抽"放着索引不用,跑去执行全表扫描
相关推荐
倔强的石头_8 小时前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库
SelectDB10 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
jiayou642 天前
KingbaseES 表级与列级加密完全指南
数据库·后端
GBASE2 天前
G术时刻 |GBase 8s数据库事务并发控制之封锁技术介绍(下)
数据库
xiezhr3 天前
逛GitHub发现了一款免费的带AI功能的数据库管理工具
数据库·ai编程·dba
唐青枫4 天前
MySQL JSON 实战详解:从存储、查询、更新到 JSON_TABLE 与索引
sql·mysql
吃糖的小孩4 天前
给 QQ AI 机器人设计“可控记忆”:会话摘要、手动长期记忆与角色卡边界
数据库
小满8784 天前
5.Mysql事务隔离级别与锁机制
mysql
笃行3504 天前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行3505 天前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库