MySQL中8.0为啥引入索引跳跃扫描(Index Skip Scan)

server/2024/10/20 2:55:14/

索引跳跃扫描(Index Skip Scan) 是一种优化查询的技术,尤其在联合索引中用于减少扫描的无效行数。它通过"跳跃"式的扫描方式,避免了对索引中无用部分的扫描,从而提升查询效率。这种技术适合特定场景,并有一定的优缺点。

一、索引跳跃扫描的原理

索引跳跃扫描利用的是联合索引中非首列(非最左前缀)的索引列,来提高查询效率。例如,如果你有一个复合索引 (A, B),在传统的 B-Tree 索引中,只有当查询条件包含 A 列时,索引才会生效。但在跳跃扫描中,即使 A 没有出现在查询条件中,仍然可以通过扫描 B 列来有效查询。

跳跃扫描会逐步扫描 A 列的每一个可能值,然后在每个 A 值下查找 B 列中符合条件的记录。这样避免了扫描大量无关记录,提升了查询性能。

二、优点和缺点

优点
  1. 提高查询效率:对于联合索引,如果查询条件只涉及非最左前缀列,跳跃扫描能够提高查询效率,减少全表扫描的次数。
  2. 减少 I/O 操作:通过避免扫描无效的索引行,跳跃扫描减少了对数据页的访问,从而节省了 I/O 操作。
  3. 降低索引空间要求:在某些场景下,可以减少为查询额外建立索引的需求,因为即使只使用了非首列,跳跃扫描也能利用现有的复合索引。
缺点
  1. 不适合高基数列:跳跃扫描对低基数列(值不多但重复率高的列)有较好的效果。但如果参与跳跃扫描的列基数高,可能需要大量跳跃,反而影响效率。
  2. 无法替代覆盖索引:对于那些经常查询的列,跳跃扫描并不能代替为每个列创建单独的索引。对于常用列,覆盖索引的效果会更好。
  3. 不适用于所有查询类型:跳跃扫描仅在某些查询模式下有效,特别是当查询条件中不包含索引的最左前缀列时。如果最左列经常被查询,跳跃扫描无法发挥作用。

三、适用场景

索引跳跃扫描通常适用于以下场景:

  • 联合索引查询:当查询条件不包括索引的最左前缀列,而仅包括后面的列时,可以使用跳跃扫描。
  • 低基数列查询:对于列值种类少、重复率高的列,跳跃扫描可以减少扫描无效记录的时间。
  • 避免额外索引:当现有的联合索引足够支持查询,而不想为特定列额外创建索引时,跳跃扫描是一种权衡。

四、Java 中索引跳跃扫描的模拟

下面我们通过 Java 代码来模拟跳跃扫描的原理。假设有一个联合索引 (A, B),我们需要查询只涉及 B 列的记录。

数据结构定义
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;class Record {int a; // 索引A列int b; // 索引B列String data; // 记录的数据public Record(int a, int b, String data) {this.a = a;this.b = b;this.data = data;}
}public class IndexSkipScan {// 模拟联合索引 (A, B),这里我们使用 TreeMap 存储排序的索引private TreeMap<Integer, List<Record>> index;public IndexSkipScan() {index = new TreeMap<>();}// 插入数据public void insert(int a, int b, String data) {Record record = new Record(a, b, data);index.computeIfAbsent(a, k -> new ArrayList<>()).add(record);}// 跳跃扫描查询 (根据B列查询)public List<Record> skipScan(int targetB) {List<Record> result = new ArrayList<>();// 逐步扫描 A 列的每一个值,然后在每个 A 值下查找 B 列的匹配项for (Integer key : index.keySet()) {for (Record record : index.get(key)) {if (record.b == targetB) {result.add(record); // 找到匹配的记录}}}return result;}public static void main(String[] args) {IndexSkipScan skipScan = new IndexSkipScan();// 插入一些数据skipScan.insert(1, 10, "Record1");skipScan.insert(1, 20, "Record2");skipScan.insert(2, 10, "Record3");skipScan.insert(3, 30, "Record4");skipScan.insert(2, 40, "Record5");// 使用跳跃扫描查询 B 列为 10 的记录List<Record> result = skipScan.skipScan(10);// 打印结果for (Record record : result) {System.out.println("Found Record: A=" + record.a + ", B=" + record.b + ", Data=" + record.data);}}
}
代码说明
  1. 使用 TreeMap 模拟联合索引 (A, B),其中 A 列作为键,B 列作为次键存储 Record 对象。
  2. skipScan() 方法模拟跳跃扫描,通过遍历所有 A 列的值,并在每个 A 值对应的记录中,查找匹配的 B 列值。
  3. 在示例中,我们插入了几条记录,并使用跳跃扫描查询 B=10 的记录。
输出结果
Found Record: A=1, B=10, Data=Record1
Found Record: A=2, B=10, Data=Record3

索引跳跃扫描优化(Index Skip Scan) 是 MySQL 在某些情况下自动进行的查询优化技术,它并不是通过特定的 SQL 语法触发,而是在满足一定条件下,由 MySQL 的查询优化器自动决定是否使用。不过,开发者可以通过合理设计 SQL 查询和索引来引导优化器使用索引跳跃扫描。

五、索引跳跃扫描的触发条件

索引跳跃扫描并不是总能触发,通常需要满足以下条件:

  1. 有一个复合索引:该复合索引需要包含多个列,例如 (a, b)(a, b, c)
  2. 查询条件不包含最左列:查询中使用了联合索引的非最左列。例如,查询中只使用了 b 列,而没有 a 列。
  3. 索引的区分度较低:跳跃扫描往往适用于索引的最左列的重复值较多的情况,因为这时跳过部分记录的开销较低。

六、如何引导 MySQL 使用索引跳跃扫描

尽管 MySQL 会自动决定是否使用索引跳跃扫描,但有一些 SQL 编写和索引设计的技巧可以引导 MySQL 更好地使用这种优化。

  1. 设计联合索引:创建适合查询的联合索引,例如 (a, b),这样在查询条件不包含 a 但包含 b 时,MySQL 可能会使用跳跃扫描。

  2. 避免使用最左列:如果你希望 MySQL 使用跳跃扫描,查询中不应该使用联合索引的最左列。例如:

    SELECT * FROM table WHERE b = 'value';
    
  3. 使用 EXPLAIN 查看执行计划:可以通过 EXPLAIN 查看 MySQL 的执行计划,看看是否触发了索引跳跃扫描优化。

    例如:

    EXPLAIN SELECT * FROM table WHERE b = 'value';
    

    在执行计划中,如果看到索引部分显示使用了联合索引,并且查询条件没有最左列,说明可能触发了跳跃扫描。

七、总结

  • 索引跳跃扫描 是 MySQL 查询优化器在某些场景下自动使用的优化技术,打破了联合索引“最左前缀”的限制,可以在未使用最左列的情况下,通过索引扫描找到符合条件的记录。
  • 引导跳跃扫描:可以通过设计合理的联合索引和查询语句来引导 MySQL 使用这种优化,但是否使用由优化器决定。
  • 优缺点:跳跃扫描能够提升某些查询的性能,但并不适用于所有场景,特别是在索引的最左列区分度高的情况下,跳跃扫描的开销可能较大。

http://www.ppmy.cn/server/133219.html

相关文章

Java项目-基于Springboot的在线外卖系统项目(源码+说明).zip

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

torch.nn.ModuleList介绍

torch.nn.ModuleList 是 PyTorch 中的一个容器类&#xff0c;用于存放多个子模块&#xff08;nn.Module&#xff09;&#xff0c;并将这些子模块注册为当前模块的属性。与 Python 原生的 list 类似&#xff0c;它可以存储一组模块&#xff0c;但是与普通的 Python 列表不同&…

特步引入IPD管理,钉钉项目 Teambition 助力高效产品研发管理

中国是全球第二大消费市场&#xff0c;运动鞋服行业拥有着巨大的发展潜力。在过去五年时间里&#xff0c;随着中国产品品牌和质量的提升&#xff0c;体育市场的占有率格局发生了显著变化&#xff0c;不同于部分国际品牌巨头营收持续减弱&#xff0c;国产领军体育运动品牌「特步…

vue video播放m3u8监控视频

很关键的问题 vite创建的项目不需要import ‘videojs-contrib-hls’ 导入就报错 直接添加如下代码即可 html5: {vhs: {overrideNative: true},nativeVideoTracks: false,nativeAudioTracks: false,nativeTextTracks: false} 下面是完整组件示例 <template><div>…

PyTorch 的 DataLoader 类介绍

DataLoader 类 功能与作用 PyTorch 是一个流行的开源机器学习库&#xff0c;它提供了一个名为 DataLoader 的类&#xff0c;用于加载数据集并将其封装成一个可迭代的对象。DataLoader 可以自动地将数据集划分为多个批次&#xff0c;并在训练过程中迭代地返回这些批次。是用于加…

如何分离人声和背景音乐?精准音频分离,提升你的作品质量

在音频编辑和处理的领域中&#xff0c;分离人声和背景音乐是一项颇具挑战的任务&#xff0c;但也是众多音频爱好者和专业人士经常面临的需求。无论是为了制作卡拉OK伴奏、提升视频制作质量&#xff0c;还是进行音乐分析和研究&#xff0c;掌握人声与背景音乐的分离技术都显得至…

学习笔记——交换——STP(生成树)工作原理

三、工作原理 STP的基本原理是在一个有二层环路的网络中&#xff0c;交换机通过运行STP&#xff0c;自动生成一个没有环路的网络拓扑。这个无环网络拓扑也叫做STP树(STP Tree)&#xff0c;树节点为某些交换机&#xff0c;树枝为某些链路。当网络拓扑发生变化时&#xff0c;STP…

springboot031教师工作量管理系统(论文+源码)_kaic

教师工作量管理系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过分析教师工作量管理系统管理的不足&#xff0c;创建了一个计算机管理教师工作量管理系统的方案。文章…