目录

  • 一. InnoDB 数据记录存储结构
  • 二. InnoDB索引页结构
  • 三. 简单总结

一. InnoDB 数据记录存储结构

  1. 在使用InnoDB作为存储引擎时,最小的存储单位为页,一页大小为16384字节也就是16kb, 其中有132个字节用来保存元数据相关信息,27个字节用来保存当前记录的附加信息, 一条记录的存储结构为:
  1. 变长字段列表中保存了数据类型为可变超度的例如Varchar,字段的实际长度
  2. Null值列表: MySQL在存储允许为null的字段时会通过Null值列表特殊处理,会在这个列表中对字段是否允许为null进行标识
  3. 记录头信息: delete_mask标记该记录是否被删除,n_owned标记该记录的记录数, record_type当前记录的类型,next_record下一条记录的相对位置
  4. DB_ROW_ID: 没有主键,并且没有唯一键时自动生成的主键
  5. DB_TRX_ID: 事物id
  6. DB_ROLL_PTR: 回滚指针
  1. 问题: 使用InnoDB时一页为16kb, 当存储实际数据大小超过16KB时怎么办,这里就牵扯到了MySQL的行格式
  2. 行格式: InnoDB存储单位是页,但是MySQL在存储数据时是按照一行来进行存储的,这个存放方式称为行格式,MySQL中支持4种不同类型的行格式(存储格式):
  1. Compact、Redundant(比较老,可以看为是静态的,mysql5.0之后使用Compact),
  2. Dynamic,Compressed(这两种时动态的,5.7之后默认Dynamic)
  1. 当使用Compact 或 Redundant行格式时,会提供出专门的溢出页,实际的存储记录中用来保存一个字段实际数据的位置,最大只会保存768个字节,超过部分会保存到溢出页,保存当前数据所在溢出页的地址值(如上图,有列1值,如果列1值超过786超过部分就保存到溢出页,然后列1中保存超过部分数据所在溢出页的地址值)
  2. 当使用Dynamic或Compressed行格式时,字段的实际数据有专门的存放位置,存储记录中保存字段数据的位置存储的是指向实际数据的地址值
  3. MySQL中有规定一个页最少存储2条记录,在使用Compact格式时如果不想出现数据溢出,那么132+2*(27+n)<16384,也就是一行数据大小不能超过8100左右

二. InnoDB索引页结构

  1. 首先要知道在使用InnoDB是如果表中有主键,主键就是主索引,如果没有主键,会使用表中设置了唯一索引的字段为主索引,如果两个都不存在InnoDB内有存在一个长度为6字节的rowId, 会使用该数据作为主索引,也就是说只要时InnoDB下的表都存在一个主索引,所有数据都是基于这个主索引进行存储的
  2. 上面说的是存储记录结构,这个记录时存在InnoDB页中,那么页中的详细信息有哪些
  1. FileHeader: 文件头部,存储了当前页的描述信息,例如当前页的页类型,页编号,上一页与下一页的地址等
  2. PageHeader: 页面头部,例如记录了当前页存储了多少条记录,多少个槽,第一条记录的地址等等
  3. Infimum+Supremum: 两个虚拟行记录,mysql插入的,标记了当前页面的最小行记录和最大行记录
  4. UserRecords: 真实数据(上面说的记录数据就是存在这个位置的),当前页已使用空间
  5. FreeSpace: 当前页空闲空间
  6. PageDirectory: 页面目录,记录了页面中一些数据存储的相对外置
  7. FileTrailer: 文件尾部,用来校验当前页是否完整,在FileHeader文件头部实际还存在另外一个"校验和",通过这两个"校验和"比对,防止数据丢失
  1. 行记录结构中记录头信息delete_mask与数据删除: B+树中页面通过链表连接,在执行删除操作时为减少链表的维护,并不是真实删除,而是设置delete_mask标识为删除,MySQL会获取这些被标记为删除状态的记录添加到一个专门的垃圾链表中,当下次存储数据打到这个删除位置时,覆盖并修改delete_mask状态即可
  2. 页面中的多条记录时怎么连接的: 通过Infimum最小记录与Supremum最大记录连接的, 在添加数据时MySQL会为每一条数据添加两个虚拟行记录,这两个行记录就相当于链表节点中当前节点的位置,与下一个节点的位置(单向链表)
  3. 页面中的PageDirectory页面目录: 一个页面中的多条数据组成一个单向链表,通过Infimum最小记录与Supremum最大记录连接, 但是单向链表查询性能不好2/n, 通过PageDirectory页面目录实现快速查找, MySQL会通过Infimum最小记录与Supremum最大记录对一个页中的多条数据进行分组,将分组后每个组中最后一条记录的地址偏移量存入PageDirectory中(这个地址偏移量称为slot 槽),在查询数据时,当定位到该数据所在页后,使用二分查找法在PageDirectory中定位到数据所在的槽,拿到槽中Infimum最小的记录,遍历获取指定数据,如下图:
  1. 查询数据定位到页后,使用二分查找法在PageDirectory中定位到该数据所在的槽
  2. 例如当前查询数据定位到槽1
  3. 拿到槽1中Infimum最小的数据,然后通过Supremum获取指定数据
  1. 索引页是怎么管理的,MySQL中提出了系统表空间(针对MySQL服务本身的)与独立表空间(针对自定义表数据的),每个表对应一个"表名.ibd"文件,这个文件就可以认为是当前表的独立表空间

  2. 页是怎么存的, 我们使用InnoDB创建表时,每张表都会对应一个"表名.ibd"文件, 用来存储当前表的数据页,内部包含了实际数据信息,与索引相关信息,页的FileHeader中保存了当前页的描述信息,例如当前页的页类型,页编号,上一页与下一页的地址等,并且会记录当前页属于哪个表空间也就是哪个".ibd"文件,其中页号由4个字节组成,通过这4个字节进而了解到一个表空间中最多可以存储21亿左右个页,拿一页16kb大小,一个表空间最大能够存储大概21亿*16kb=64t左右的数据

  3. 通过FileHeader文件头中的页号了解到一个表空间中最多可以存储21亿左右个页, 为了提高MySQL的检索性能,会针对页进行分区,64个页组成一个分区(大概1M),并且会根据区划分不同的组,每个组中最大可以存储256个区,针对组又划分不同的段

  4. 表空间在管理页时,针对页进行分区的好处是什么:减少随机io, 在一棵b+数中多个页是通过双向链表连接的(页中的行数据是通过单向链表连接的),会出现一个问题,在逻辑上两个相邻的数据页,对应到物理上可能是不相邻的,那么在查找时就可能出现随机io的问题,为了防止这个问题,规定一个区中的所有页在物理上也必须是相邻的,在申请创建新页时相邻,并且如果表的数据量特别大,在申请时会直接按照区为单位进行申请

  5. 表空间在管理页时,分段的好处是什么: 段是一个逻辑概念,在InnoDB的主索引树分为叶子节点跟非叶子节点,由于叶子节点与非叶子节点存储数据的不同将不同节点的数据放入不同的段中(叶节点段, 非叶节点段),更方便查询数据,另外还存在回滚段

  6. 树高估算

在InnoDB中最小存储单元是页,默认大小为16KB,一个指针为6个字节,如果主键使用bigint类型那么一个主键占8个字节,计算下来在InnoDB中根节点中可以存储16k/(6+6)=1170,也就是根节点下有1170个子节点,那么这1170个子节点下每个节点都会有1170个子节点,如果当前树高为3层,那么就是1170 * 1170=1368900约等于136万,因为一个页为16k,假设一条数据大小也是16k那么这个三层树只可以存储大概136万条数据,如果一条数据为1k,那么就可以存储1170 * 1170 * 16=21902400约2900万左右数据,在相同数据量情况下,单条数据越大,树越高
3. 在通过索引获取数据时实际走的是二分查找进行查询的,以主键索引为例,io次数等于树高-1,因为根节点是常驻内存的,树越高io次数也就越多

三. 简单总结

  1. 通过上面了解到使用InnoDB存储引擎的记录结构,行格式,与索引页结构, 索引页数据会存储在"表名.ibd" 表空间中
  1. InnoDB在建表时如果有主键会基于主键构建主索引,如果没有主键会选择一个设置了唯一索引的列作为主索引,如果两个都没有会自动创建一个为6个字节的row_id作为主索引使用,反正是InnoDB时一定会有主索引,然后基于主索引存储数据
  2. 数据是按照行格式一行一行进行存储在页中的,MySQL会为每一条数据行添加两个虚拟记录Infimum最小记录与Supremum最大记录,这两个行记录就相当于链表节点的当前节点的位置,与下一个节点的位置(单向链表)
  3. 为了提高查询性能,索引页中存在PageDirectory页面目录,MySQL会通过行记录的Infimum最小记录与Supremum最大记录对一个页中的多条数据进行分组,将分组后每个组中最后一条记录的地址偏移量存入PageDirectory中(这个地址偏移量称为slot 槽),在查询数据时,当定位到该数据所在页后,使用二分查找法在PageDirectory中定位到数据所在的槽,拿到槽中Infimum最小的记录,遍历获取指定数据
  4. 表空间在管理索引页时,为了提高查询性能,将多个页划分为区, 多个区划分为组,在组的上层又存在段的概念

九. MySQL InnoDB 底层结构相关推荐

  1. MySQL innoDB底层基础原理总结

    MySQL innoDB底层基础原理 前言:由于正在准备之后的实习面试,故总结了一部分MYSQL innoDB基础的问题,回答全为自己组织的语言,若有错各位大佬可及时指出,大家共同进步,谢谢. 1.i ...

  2. 【mysql innodb索引结构B+树】

    [mysql innodb索引结构B+树] 为什么Mysql中Innodb的索引结构采取B+树? B树 B树的两个明显特点 树内的每个节点都存储数据 叶子节点之间无指针相邻 B+树 B+树的两个明显特 ...

  3. 一篇文章让你搞懂Mysql InnoDB内存结构

    前言 我们都熟悉mysql数据库服务架构,也清楚SQL的执行顺序,Mysql的数据在磁盘和内存中的存储结构是采用B+树的数据结构,但是在InnoDB引擎中,数据在内存和磁盘中的展示形式以及怎么和Mys ...

  4. mysql innodb 索引结构_Mysql 学习笔记:InnoDB 索引结构浅析

    索引是检索图书资料的一种工具,把书刊中的内容或项目分类摘录,注明页数,按一定次序排列. 针对不同的数据存储结构有不同的数据查找方式. 1. 数据结构 1.1 B树 B树又名平衡多路查找树,主要用于文件 ...

  5. MySQL InnoDB事务结构体代码变量全攻略(附源码)

    写在前面 ​ InnoDB是MySQL的一个存储引擎,支持事务,支持非堵塞的一致性读,物理存储结构是Page,每个事务都有回滚日志,重做日志,事务还会有死锁检测,各种各样不同的锁等等. 翻看InnoD ...

  6. Mysql索引底层结构解析

    从一个实战案例了解索引 我们可以看到这有一个87万的表 没加索引之间执行 SELECT * from t_program WHERE code = '1a5712ef6a864ccca9313aeda ...

  7. MySQL索引底层实现原理 MyISAM非聚簇索引 vs. InnoDB聚簇索引

    MySQL索引底层实现原理 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 我们知道,数据库查询是数据库的 ...

  8. 《MYSQL是怎样运行的》笔记|配置文件|系统变量|字符集|InnoDB存储结构|数据页结构|索引结构与使用|数据目录|表空间|连表原理|查询优化|BufferPool|事务|redo与undo|锁

    <MYSQL是怎样运行的>笔记 前记: 历时15天,笔记+看书.完成于2022.2.5. 本书是讲具体的数据库实现,而数据库系统概念见:https://blog.csdn.net/qq_4 ...

  9. mysql引擎层存储层_MySQL存储底层技术:InnoDB底层原理解读

    原标题:MySQL存储底层技术:InnoDB底层原理解读 存储引擎 很多文章都是直接开始介绍有哪些存储引擎,并没有去介绍存储引擎本身.那么究竟什么是存储引擎?不知道大家有没有想过,MySQL是如何存储 ...

最新文章

  1. Linux 桌面玩家指南:17. 在 Ubuntu 中使用 deepin-wine,解决一些依赖 Windows 的痛点问题
  2. opencv相机标定
  3. 给Jquery easyui 的datagrid 每行增加操作链接(转)
  4. 策划文档html,html代码整理.doc
  5. Flink On Yarn模式,为什么使用Flink On Yarn?Session模式、Per-Job模式、关闭yarn的内存检查,由Yarn模式切换回standalone模式时需要注意的点
  6. Java扑克牌(洗牌Collections.shuffle)
  7. vant 动态 粘性布局_CSS Viewport 单位,很多人还不知道使用它来快速布局!
  8. 网站QQ全屏PHP代码,QQ技术导航升级版 超级导航美化版带后台版 PHP源码
  9. 微积分和概率统计有什么用?用来表白呀!
  10. Be动词的缩写形式_3
  11. python樱花树代码_【推荐】手把手教你如何用Python画一棵漂亮樱花树含源码
  12. Spark 在 Window 环境下的搭建
  13. access mysql连接字符串_[数据库连接字符串] Access 连接字符串
  14. jwt (JSON Web Token)官方说明
  15. python中使用Opencv进行人脸检测
  16. 三国志战略版交易助手攻略
  17. 单片机最小系统着实让人着迷
  18. 音频、音频属性-采样精度、比特率、音频格式
  19. html5猜数字游戏代码,js猜数字小游戏的简单实现代码
  20. SwiftUI 语音合成与语言识别教程之 03 实现录音文件转文字(含完整项目源码)SFSpeechURLRecognitionRequest

热门文章

  1. Post Office
  2. 如何使用python读取modbus/TCP协议数据
  3. 关于最近word模板以及word转pdf的总结
  4. STM32 CubeMX配置ADC+DMA进行FFT(1)
  5. [原]我和她同居的日子 一
  6. QQ相关(一)【导出所有QQ好友】
  7. 锻造宝剑!如何用一款手机打造一个移动渗透工具箱??
  8. 高德地图API创建地理围栏
  9. 右键新建的文档是wps类型的而不是office类型的解决方案
  10. mix2s android p,待遇堪比“亲儿子” 小米MIX 2s迎来Android P升级