mysql8 loose index skip scan 特性加速分组查询性能

前言

要理解Loose Index Scan(松散索引扫描) 如何加速 GROUP BY,核心是抓住「索引有序性 」和「跳过无效数据、只取分组核心值」这两个关键点------它彻底避开了"遍历所有数据→临时表分组"的低效路径,直接从有序索引中"精准提取"分组结果。

先看「常规 GROUP BY」的低效逻辑(对比更易理解)

假设表 t1 有索引 idx(c1,c2),数据如下(索引是有序存储的,所以实际索引中 c1 的值是连续的):

c1 c2
1 10
1 20
2 30
2 40
3 50

如果执行 SELECT c1, MIN(c2) FROM t1 GROUP BY c1;常规方式的执行步骤是:

  1. 扫描全表(或全索引),读取所有 5 行数据;
  2. 创建临时表,把 c1=1 的两行、c1=2 的两行、c1=3 的一行分别归集;
  3. 对每个分组计算 MIN(c2)
  4. 返回结果。

这个过程要遍历所有数据,还需要临时表,数据量越大效率越低。

再看「Loose Index Scan」的加速逻辑

因为索引 idx(c1,c2)有序的 (BTREE 索引特性),c1 相同的记录在索引中是连续排列的。Loose Index Scan 利用这一点,只读取每个分组的"关键值",跳过同分组的其他数据

步骤拆解(还是上面的查询 SELECT c1, MIN(c2) FROM t1 GROUP BY c1;):

  1. 定位索引中第一个 c1=1 的记录,其 c2=10------因为索引有序,同组后续的 c1=1 记录的 c2 一定≥10,所以 MIN(c2) 直接确定为 10,无需读取 c1=1 的下一条记录(c2=20)
  2. 跳过所有 c1=1 的剩余记录,直接定位到第一个 c1=2 的记录,其 c2=30------同理,MIN(c2)=30,跳过 c1=2 的下一条记录(c2=40);
  3. 跳过所有 c1=2 的剩余记录,定位到第一个 c1=3 的记录,其 c2=50------MIN(c2)=50
  4. 直接返回结果,全程只读取了 3 条记录(每个分组 1 条),且无需创建临时表

核心加速点总结:

维度 常规 GROUP BY Loose Index Scan
数据读取量 遍历所有符合条件的记录 仅读取每个分组的"首条关键记录"
临时表 必须创建(归集分组) 无需创建
计算逻辑 先归集所有数据,再算聚合 直接从索引首条记录推导聚合结果
时间复杂度 O(N)(N 为总记录数) O(M)(M 为分组数,M << N)

再举一个带范围条件的例子,更显"松散"的优势

如果查询是 SELECT c1, MIN(c2) FROM t1 WHERE c1 < 3 GROUP BY c1;

  • 常规方式:读取 c1<3 的所有 4 条记录(c1=1 的 2 条 + c1=2 的 2 条),临时表分组后计算;
  • Loose Index Scan:仅读取 c1=1 的第一条、c1=2 的第一条,共 2 条记录,直接得出结果,跳过了同组的其他 2 条记录。

为什么叫"松散"?

"松散"的核心是------它不"紧密"遍历索引的每一个键值,而是跳过同分组的所有冗余记录,只抓每个分组的"锚点"(首条记录),就像从有序的数组中"跳着找"分组,而非逐个遍历。

关键前提:为什么能"跳着找"?

必须满足「GROUP BY 列是索引最左前缀」+「聚合函数仅 MIN/MAX 且列紧跟分组列」,本质是:

  1. 索引有序性保证了"同分组的记录连续",所以首条记录就能确定 MIN/MAX;
  2. 索引最左前缀保证了"分组列在索引中是最优先的排序维度",能直接按分组列跳着定位。

如果不满足这些条件(比如用 SUM、GROUP BY 列不是最左前缀),就无法"跳着找",只能退化为 Tight Index Scan 或常规方式。

简单总结:Loose Index Scan 把 GROUP BY 的执行成本,从「依赖数据总量」降到了「依赖分组数量」,分组数远小于数据量时,加速效果极其显著。

官方文档

https://dev.mysql.com/doc/refman/8.0/en/group-by-optimization.html

相关推荐
学习指针路上的小学渣13 小时前
mysql笔记
mysql
Yvonne爱编码13 小时前
数据库---Day3 数据类型
数据库
kc胡聪聪13 小时前
MySQL的主从复制与读写分离
mysql
羑悻的小杀马特13 小时前
30 分钟零基础搭建 Home Assistant,解锁全屋智能新境界
数据库·人工智能
皙然14 小时前
深入理解 MySQL 事务:从基础到实战,一篇吃透
数据库·mysql
我科绝伦(Huanhuan Zhou)14 小时前
MySQL数据库备份管理系统新增备份任务巡检功能
运维·数据库·mysql
吠品14 小时前
Docker Desktop部署Weaviate向量数据库:从配置到生产环境全流程
数据库·oracle·eureka
tuokuac14 小时前
什么情况下type为index
mysql
倔强的石头10614 小时前
【Linux指南】基础IO系列(三):Linux 系统 IO 接口 —— 深入内核的文件操作
linux·数据库
拾起零碎14 小时前
U8/领料申请单SQL server触发器,如果自定义项13有值,把数量修改成件数乘以自定义项13,如果恰好件数等于现存量,则数量同步出空
数据库