MySQL:B+树索引

InnoDB索引方案

为了使用二分法快速定位具体的目录项,假设所有目录项都可以在物理存储器上连续存储,有以下问题:

  • InnoDB使用页为管理存储空间的基本单位,最多只能保证16KB的连续存储空间,记录数据量多可能需要非常大的连续存储空间才能放下所有目录项
  • 增删操作,如果把某页的记录都删除,则该页及目录项都没有存在的必要,如果要把后面的目录项都向前移,牵一发而动全身;如果不移动作为冗余放在目录项列表,浪费存储空间
    复用存储用户记录的数据页来存储目录项,record_type=1标志目录项记录
    在这里插入图片描述

目录项记录和普通用户记录的不同点

  • 目录项记录record_type为1,普通用户记录的record_type为0
  • 目录项记录只有主键值和页的编号两个列,普通用户记录的列由用户自己定义,可能包含多列,还有InnoDB自己添加的隐藏列
  • 只有目录项记录的min_rec_flag属性为1,普通用户记录的min_rec_flag属性都是0
    在这里插入图片描述

在这里插入图片描述

如果存储目录项的页也很多,则为这些存储目录项记录的页再生成一个更高级的目录
真正的用户记录都存放在B+树🌲的叶子节点上【第0层】
Page Header部分PAGE_LEVEL属性代表这个数据页作为节点在B+树中的层级

聚簇索引

B+树本身就是一个目录/一个索引,有以下两个特点:

  • 使用记录主键值的大小进行记录和页的排序
    • 页【包括叶子节点和内节点】内的记录按照主键的大小排序排成一个单向链表,页内的记录被划分成若干个组,每个组中主键值最大的记录在页内的偏移量会被当作槽依次放在页目录项中,可以在页目录中通过二分法快速定位到主键列等于某值的记录
    • 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表
    • 存放目录项记录的页分为不同的层级,在同一层级中的页也是根据页中目录项记录的主键大小排序排成一个双向链表
  • B+树的叶子节点存储的是完整的用户记录【所有列的值,包括隐藏列】
    在InnoDB存储引擎中,聚簇索引就是数据的存储方式【索引即数据,数据即索引】

二级索引

聚簇索引只能在搜索条件是主键值时才能发挥作用【B+树中的数据都是按照主键进行排序】
多建几颗B+树,不同的B+树中的数据采用不同的排序规则
在这里插入图片描述

与聚簇索引的不同:

  • 使用记录c2列的大小进行记录和页的排序
    • 页【包括叶子节点和内节点】内的记录是按照c2列的大小顺序排成的一个单向链表,页内的记录被划分成若干个组,每个组中c2列值最大的记录在页内的偏移量会被当作槽一次存放在页目录中
    • 各个存放用户记录的页也是根据页中记录的c2列大小顺序排成的一个双向链表
    • 存放目录项记录的页分为不同的层级,在同一层级中的页也是根据页中目录项记录的c2列大小顺序排成一个双向链表
  • B+树的叶子节点存储的不是完整的用户记录,而只是c2列+主键这两个列的值
  • 目录项记录中不再是主键+页号的搭配,变成了c2列+页号的搭配
    C2列并没有唯一性约束,也就是说满足搜索条件c2=4的记录可能有多条,只需要在该B+树的叶子节点处定位到第一条满足搜索条件c2=4的记录,然后沿着由记录组成的单向链表一直向后扫描即可**【页内的记录是按照c2列的大小顺序排成的一个单向链表】,各个叶子节点组成了双向链表**,搜索完了本页记录后可以跳到下一页面中第一条记录继续向后扫描
    查找c2=4记录的过程:
  1. 确定第一条符合条件的目录项记录所在的页【定位到页42(2<4<9)】
  2. 通过第一条符合条件的目录项记录所在的页面确定第一条符合条件的用户记录所在的页【定位到第一条符合c2=4的用户记录所在页为34/35(2<4≤ 4)】
  3. 在真正存储第一条符合条件的用户记录的页中定位到具体的记录【如果在页34定位到第一条就不需要再到页35定位第一条记录】
  4. 这个B+树只记录了c2和主键两个列,在定位到第一条符合条件的用户记录后,需要根据该记录中的主键信息到聚簇索引中查找到完整的用户记录,这个通过携带主键信息到聚簇索引中重新定位完整记录的过程也称为回表,然后再返回到这颗B+树叶子节点处沿单向链表继续向后搜索其他满足条件的记录【找到一条就去聚簇索引找到完整记录】
    因为需要回表才能获取完整的记录,这种B+树也称为二级索引/辅助索引

联合索引/复合索引/多列索引

可以同时以多个列的大小作为排序规则,即同时为多个列建立索引
在这里插入图片描述

  • 每条目录项记录都由c2列、c3列、页号这三部分组成,记录先按c2列的值进行排序,c2相同的情况下再按照c3列的值进行排序
  • B+树叶子节点处的用户记录由c2列、c3列和主键c1组成
    本质上也是一个二级索引

InnoDB中B+树索引的注意事项

  1. 根页面万年不动窝【页号不再改变】【存簇索引根节点在某个页面,数据字典中的一项信息】
    1. 每当为某个表创建B+树索引【聚簇索引默认存在】时,就会为这个索引创建一个根节点页面,最开始表中没有数据的时候,每个B+树索引对应的根节点中既没有用户记录也没有目录项记录
    2. 向表中插入用户记录时,先把用户记录存储到这个根节点中
    3. 在根节点中可用空间用完时继续插入记录,1⃣️将根节点中所有记录复制到一个新分配的页a中,2⃣️对这个新页进行页分裂操作,3⃣️得到另一个新页b,新插入的记录会根据键值【主键值/二级索引对应的索引列值】的大小分配到页a/页b中,根节点升级为存储目录项记录的页,需要把页a和页b对应的目录项记录插入到根节点中【由空叶子节点形成树的过程】
  2. 内节点中目录项记录的唯一性
    1. 目录项记录的内容是索引列加页号的搭配,但对于二级索引来说不够严谨,为了让新插入的记录找到在哪个页,需要保证B+树同一层内节点的目录项记录除页号字段以外是唯一的【二级索引内节点的目录项记录的内容由:索引列的值、主键值、页号构成】

    2. 在这里插入图片描述

    3. 图6-16如果插入列值为1的记录,则该记录会找不到该往页4插还是页5

    4. 如图6-17,先把新记录的列值与页3各目录项记录的列值比较,如果列值相同,可以接着比较主键,B+树同一层中不同目录项记录的列值+主键的值肯定不同,最后肯定能定位到唯一一条目录项记录

    5. 对二级索引记录来说,先按二级索引列的值进行排序,如果列值相同的情况下,再按主键值排序,为c2列建立索引相当于为(c2,c1)列建立一个联合索引

    6. 对于唯一二级索引【当为某列或列组合声明UNIQUE属性时,便会为这个列或列组合建立唯一二级索引】来说,也可能会出现多条记录键值相同的情况【声明为UNIQUE属性的列可能存储多个NULL值;MVCC服务】,唯一二级索引的内节点的目录项记录也会包含记录的主键值

  3. 一个页面至少容纳2条记录
    1. InnoDB一个数据页至少可以存放2条记录,如果只能存放一条则目录层级会非常多,最后叶子节点也只有一条记录,效率大打折扣
    2. 如果B+树叶子节点只存储一条记录,内节点存储多条记录也是可以发挥B+树作用的,但是为了避免B+树层级增长过高,InnoDB要求所有数据页都至少可以容纳两条记录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77043.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

THCON 2025

Crypto OTPas_ouf 用10个字符异或加密的jpg图片&#xff0c;通过头得到key再恢复原图 Mammoths Personnal Slot Machine 梅森旋转恢复 from pwn import * from randcrack import RandCrack from tqdm import trange context.log_level errorp remote(74.234.198.209, 33…

3.8 字符串的常用函数

重点&#xff1a;字符串的常用函数 #1.测试转换大小写 lower:大写->小写 upper&#xff1a;小写->大写 swapcase&#xff1a;自动将大写转小写小写转大写 print("ABC".lower()) #abcprint("abc".upper()) #ABCprint…

Docker:SkyWalking 链路追踪的技术指南

1、简述 Apache SkyWalking 是一个开源的 APM(应用性能监控)工具,能够实现分布式系统的全链路监控、性能分析以及服务依赖关系分析。SkyWalking 支持多种语言的探针,提供强大的可视化监控和分析能力,是微服务架构下性能调优和问题排查的利器。 样例代码: https://gitee.…

[Lc] 最长公共子序列 | Fenwick Tree(树状数组):处理动态前缀和

目录 LCR 095. 最长公共子序列 题解 Fenwick Tree&#xff08;树状数组&#xff09;&#xff1a;处理动态前缀和 一、问题背景&#xff1a;当传统方法遇到瓶颈 二、Fenwick Tree核心设计 2.1 二进制索引的魔法 2.2 关键操作解析 更新操作&#xff08;O(log n)&#xff0…

python3.13.0环境安装及python-docx库安装指南

1. Python环境安装 1.1 Windows系统安装Python 下载Python安装包 • 访问Python官网 • 点击"Download Python 3.x.x"&#xff08;推荐使用3.8及以上版本&#xff09; 2. 运行安装程序 • 双击下载的安装包 • 重要&#xff1a;勾选"Add Python to environmen…

前端VUE框架理论与应用(4)

一、计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如: <div id="example">{{ message.split().reverse().join() }}</div> 在这个地方,模板不再是简单的声明式逻辑。你…

MySQL:存储函数和存储过程

系列文章目录 1.MySQL编程基础 2.程序控制流语句 3.存储过程 4.游标 5.嵌入式SQL 文章目录 系列文章目录前言一、程序控制流语句&#xff1a;二、存储函数&#xff1a; 1.存储函数的特点&#xff1a;2.存储函数的定义&#xff1a;3.调用存储函数 三、存储过程&#xff1a;…

基础贪心算法集合2(10题)

目录 1.单调递增的数字 2.坏了的计算器 3.合并区间 4.无重叠区间 5. 用最少数量的箭引爆气球 6.整数替换 解法1&#xff1a;模拟记忆化搜索 解法2位运算贪心 7.俄罗斯套娃信封问题 补充.堆箱子 8.可被3整除的最大和 9.距离相等的条形码 10.重构字符串 1.单调递增的数字…

RaabitMQ 快速入门

&#x1f389;欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨ &#x1f389;感谢各位读者在百忙之中抽出时间来垂阅我的文章&#xff0c;我会尽我所能向的大家分享我的知识和经验&#x1f4d6; &#x1f389;希望我们在一篇篇的文章中能够共同进步&#xff01;&#xff01;&…

语音识别——根据声波能量、VAD 和 频谱分析实时输出文字

SenseVoiceSmall网络结构图 ASR(语音识别)是将音频信息转化为文字的技术。在实时语音识别中,一个关键问题是:如何决定将采集的音频数据输入大模型的最佳时机?固定时间间隔显然不够灵活,太短可能导致频繁调用模型,太长则会延迟文字输出。有没有更智能的方式?答案是肯定…

AI大模型如何重塑科研范式:从“假说驱动”到“数据涌现”

📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:科研进入“模型共研”时代 传统科研范式通常以“假设→实验→验证→理论”的方式推进,这一经典路径建立在人类的认知能力与逻辑推理基础上。然而,随着数据规模的爆炸式增长与知识系统的高度复杂…

使用Python写入JSON、XML和YAML数据到Excel文件

在当今数据驱动的技术生态中&#xff0c;JSON、XML和YAML作为主流结构化数据格式&#xff0c;因其层次化表达能力和跨平台兼容性&#xff0c;已成为系统间数据交换的通用载体。然而&#xff0c;当需要将这类半结构化数据转化为具备直观可视化、动态计算和协作共享特性的载体时&…

面试题:Eureka和Nocas的区别

Eureka 与 Nacos 核心区别对比 一、功能定位与核心能力 ‌维度‌‌Eureka‌‌Nacos‌‌核心功能‌专注服务注册与发现&#xff0c;无配置管理功能‌:ml-citation{ref“1,3” data“citationList”}集成服务注册、发现、配置管理、动态DNS等‌:ml-citation{ref“1,3” data“c…

2025年4月15日 百度一面 面经

目录 1. 代理相关 从静态代理到动态代理 2. cglib可以代理被final修饰的类吗,为什么 3. JVM 体系结构 4. 垃圾回收算法 5. 什么是注解 如何使用 底层原理 6. synchronized和reentrantlock 7. 讲一下你项目中 redis的分布式锁 与java自带的锁有啥区别 8. post 请求和 ge…

AI改变生活

AI改变生活 人工智能&#xff08;AI&#xff09;在我们生活中的应用越来越广泛&#xff0c;深刻地改变了我们的工作和生活方式。以下是一些AI实际应用的实例&#xff0c;以及它们如何影响我们的日常生活。 1. 智能助手 智能助手如Siri、Alexa和Google Assistant等&#xff0…

信奥赛之c++基础(取模运算与数位分离)

🎮 数字拆解大冒险——取模运算与数位分离魔法课 🍬 第一章:糖果分装术——取模运算 🍭 分糖果游戏 7颗糖每人分3颗: 每人得到:7 / 3 = 2颗剩余糖果:7 % 3 = 1颗(%就是取模符号) 就像把糖果装袋后剩下的零散糖粒!🔧 取模运算说明书 算式比喻结果10 % 310颗糖分…

揭秘大数据 | 21、软件定义计算

老夫先将这个小系列的前两篇内容链接奉上&#xff0c;方便感兴趣的朋友一气读之。 揭秘大数据 | 19、软件定义的世界-CSDN博客 揭秘大数据 | 20、软件定义数据中心-CSDN博客 今天&#xff0c;书接上文&#xff0c;开聊软件定义计算的那些事儿&#xff01; 虚拟化是软件定义…

FPGA-DDS技术的波形发生器

1.实验目的 1.1掌握直接数字频率合成&#xff08;DDS&#xff09;的基本原理及其实现方法。 1.2在DE2-115 FPGA开发板上设计一个可调频率的正弦波和方波发生器&#xff0c;频率范围10Hz~5MHz&#xff0c;最小分辨率小于1kHz。 1.3使用Quartus II进行仿真&#xff0c;并通过S…

LeetCode[541]反转字符串Ⅱ

思路&#xff1a; 题目给我们加了几个规则&#xff0c;剩余长度小于2k&#xff0c;大于等于k就反转k个&#xff0c;小于k就全部反转&#xff0c;我们按照这个逻辑来就行。 第一就是大于等于k就反转k个&#xff0c;我们for循环肯定是i2k了&#xff0c;接下来就是判断是否大于等于…

实现定长的内存池

池化技术 所谓的池化技术&#xff0c;就是程序预先向系统申请过量的资源&#xff0c;然后自己管理起来&#xff0c;以备不时之需。这个操作的价值就是&#xff0c;如果申请与释放资源的开销较大&#xff0c;提前申请资源并在使用后并不释放而是重复利用&#xff0c;能够提高程序…