Mysql InnoDB 行格式解析

该篇是学习笔记,笔记来源于《MySQL是怎样运行的:从根儿上理解MySQL》

InnoDB 是一个将表中的数据存储到磁盘上的存储引擎,所以即使关机后重启我们的数据还是存在的。而真正处理数据的过程是发生在内存中的,所以需要把磁盘中的数据加载到内存中,如果是处理写入或修改请求的话,还 需要把内存中的内容刷新到磁盘上。而我们知道读写磁盘的速度非常慢,和内存读写差了几个数量级,所以当我 们想从表中获取某些记录时,InnoDB 存储引擎需要一条一条的把记录从磁盘上读出来么?不,那样会慢死, InnoDB 采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小 一般为 16 KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB 内容刷新到磁盘中

 InnoDB行格式

1.COMPACT行格式

大家从图中可以看出来,一条完整的记录其实可以被分为记录的额外信息和记录的真实数据两大部分,下边我 们详细看一下这两部分的组成。

1.1记录的额外信息

这部分信息是服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为3类,分别是变长字段 长度列表、NULL值列表和记录头信息,我们分别看一下

变长字段长度列

我们知道MySQL 支持一些变长的数据类型,比如VARCHAR(M) 、 VARBINARY(M) 、各种 TEXT 类型,各种 BLOB 类 型,我们也可以把拥有这些数据类型的列称为变长字段,变长字段中存储多少字节的数据是不固定的,所以我 们在存储真实数据的时候需要顺便把这些数据占用的字节数也存起来,这样才不至于把MySQL服务器搞懵,所以 这些变长字段占用的存储空间分为两部分:

  1. 真正的数据内容
  2. 占用的字节数

 在Compact 行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长 字段长度列表,各变长字段数据占用的字节数按照列的顺序逆序存放。

当列采用的是定长字符集时,该列占用的字节数不会被加到变长字段长度列表,而如果采用变长字符集时,该列占用的字节数也会被加到变长字段长度列表

列名存储内容内容长度(十进制表示)内容长度(十六进制表示)
c1'aaaa'40x04
c2'bbb'30x03
c3'd'10x01

第1条记录的存储格式:

 NULL 值列表

我们知道表中的某些列可能存储NULL值,如果把这些NULL值都放到记录的真实数据中存储会很占地方,所 以Compact 行格式把这些值为 NULL 的列统一管理起来,存储到 NULL 值列表中

 如果表中没有允许存储 NULL 的列,则 NULL 值列表不存在,,否则将每个允许存储NULL 的列对应一个 二进制位,二进制位按照列的顺序逆序排列,二进制位表示的意义如下

  • 二进制位的值为1时,代表该列的值为NULL。
  • 二进制位的值为0时,代表该列的值不为NULL。

如果此时有一个表 test ,有列 c1,c2,c3 其中三个列都允许存储null值则这3个列和二进制位的对应关系就是这样:

MySQL 规定 NULL值列表 必须用整数个字节的位表示,如果使用的二进制位个数不是整数个字节,则在字节 的高位补0。

表test 只有3个值允许为 NULL 的列,对应3个二进制位,不足一个字节,所以在字节的高位补0,效果就是这样

所以,如果test表中有两条记录 1,2,3 和1,null,null

他们所对应的NULL值列表 应该如下图:

 记录头信息

名称                大小(单位: bit)     描述
-------------------------------------------------
预留位1             1                 没有使用
预留位2             1                 没有使用
delete_mask         1                 标记该记录是否被删除
min_rec_mask        1                 B+树的每层非叶子节点中的最小记录都会添加该标记
n_owned            4                 表示当前记录拥有的记录数
heap_no            13                表示当前记录在记录堆中的位置信息
record_type        3                 表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录
next_record        16                表示下一条记录的相对位置

混个脸熟即可~

1.2 记录的真实数据

对于test表来说,记录的真实数据除了 c1 、 c2 、 c3  这几个我们自己定义的列的数据 以外,MySQL 会为每个记录默认的添加一些列(也称为隐藏列),具体的列如下

列名是否必须占用空间描述
DB_ROW_ID6 字节行ID,唯一标识一条记录
DB_TRX_ID6 字节事务ID
DB_ROLL_PTR7 字节回滚指

InnoDB 表对主键的生成策略:优先使用用户自定义主键作为主键,如果用户没有定义主键,则 选取一个Unique 键作为主键,如果表中连 Unique 键都没有定义的话,则 InnoDB 会为表默认添加一个名为 row_id 的隐藏列作为主键。所以我们从上表中可以看出:InnoDB存储引擎会为每条记录都添加 transaction_id 和 roll_pointer 这两个列,但是 row_id 是可选的(在没有自定义主键以及Unique键的情况下才会添加该列)。 这些隐藏列的值不用我们操心,InnoDB 存储引擎会自己帮我们生成的。

 因为test表 并没有定义主键,所以 MySQL 服务器会为每条记录增加上述的3个列。

Redundant行格式

的Redundant 行格式是 MySQL5.0 之前用的一种行格式,比较老了。

字段长度偏移列表

Compact 行格式的开头是 变长字段长度列表,而Redundant 行格式的开头是 字段长度偏移列表 ,与 变长字段长度列表有两处不同

  • 没有了变长两个字,意味着Redundant 行格式会把该条记录中所有列(包括隐藏列)的长度信息都按 照逆序存储到字段长度偏移列表。
  • 多了个偏移两个字,这意味着计算列值长度的方式不像Compact行格式那么直观,它是采用两个相邻数 值的差值来计算各个列值的长度
行溢出数据

对于VARCHAR(M) 类型的列最多可以占用 65535 个字节。其中的 M 代表该类型最多存储的字符数量,如 果我们使用ascii 字符集的话,一个字符就代表一个字节,我们看看VARCHAR(65535) 是否可用

MySQL 对一条记录占用的最大存储空间是有限制的,除了BLOB或者TEXT类型的列之 外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字节。所以MySQL服 务器建议我们把存储类型改为TEXT或者BLOB 的类型。这个65535 个字节除了列本身的数据之外,还包括一些 其他的数据(storage overhead ),比如说我们为了存储一个 VARCHAR(M) 类型的列,其实需要占用3部分存储 空间:

  • 真实数据
  • 真实数据占用字节的长度
  • NULL 值标识,如果该列有NOT NULL属性则可以没有这部分存储空间

如果该VARCHAR 类型的列没有 NOT NULL 属性,那最多只能存储 65532 个字节的数据,因为真实数据的长度可能 占用2个字节,NULL 值标识需要占用1个字节:

 记录中的数据太多产生的溢出

如上图 ,REPEAT('a', 65532) 是一个函数调用,它表示生成一个把字符 'a' 重复 65532 次的字符串。前边说 过,MySQL 中磁盘和内存交互的基本单位是页,也就是说MySQL是以页为基本单位来管理存储空间的,我们 的记录都会被分配到某个页中存储。而一个页的大小一般是16KB,也就是16384字节,而一个VARCHAR(M) 类 型的列就最多可以存储65532 个字节,这样就可能造成一个页存放不了一条记录的尴尬情况。

 在Compact 和 Reduntant 行格式中,对于占用存储空间非常大的列,在 记录的真实数据 处只会存储该列的一部 分数据,把剩余的数据分散存储在几个其他的页中,然后记录的真实数据处用20个字节存储指向这些页的地址 (当然这20个字节中还包括这些分散在其他页面中的数据的占用的字节数),从而可以找到剩余数据所在的页。如图:

不只是 VARCHAR(M) 类型的列,其他的 TEXT、BLOB 类型的列在存储数据非常多的时候 也会发生行溢出

Dynamic和Compressed行格式

mysql 5.7以后默认的行格式为Dynamic 这俩行格式和 Compact 行格式挺像,只不过在处理 行溢出 数据时有点儿分歧,它们不会在记 录的真实数据处存储字段真实数据的前768个字节,而是把所有的字节都存储到其他页面中,只在记录的真实数 据处存储其他页面的地址:

Compressed 行格式和 Dynamic 不同的一点是, Compressed 行格式会采用压缩算法对页面进行压缩,以节省空间。 

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

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

相关文章

【测试框架篇】单元测试框架pytest(4):assert断言详解

一、前言 用例三要素之一就是对预期结果的断言。 何为断言?简单来说就是实际结果和期望结果去对比,符合预期就测试pass,不符合预期那就测试 failed。断言内容就是你要的预期结果。断言包含对接口响应内容做断言、也包含对落DB的数据做断言。…

基础玩转物联网-4G模块如何快速实现与MQTT服务器通信

目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件准备 2.3 硬件连接 2.4 检查驱动 3 连接MQTT服务器 3.1 创建MQTT监听Topic 3.2 打开配置工具读取基本信息 3.3 设置连接参数进行数据交互 4 总结 1 前言 MQTT(Message Queuing Telemetry Transport)是一种轻…

平面机械臂运动学分析

平面机械臂运动学分析 一 整体概述1 研究步骤: 二 正向1 几何分析2 matlab 仿真模拟(1)实现效果(2)matlab代码: 3 DH矩阵计算法(1)计算公式(2)计算结果验证&a…

Hadoop、Hive、Spark的关系

Part1:Hadoop、Hive、Spark关系概览 1、MapReduce on Hadoop 和spark都是数据计算框架,一般认为spark的速度比MR快2-3倍。 2、mapreduce是数据计算的过程,map将一个任务分成多个小任务,reduce的部分将结果汇总之后返回。 3、HIv…

1.4 单元测试与热部署

本次实战实现Spring Boot的单元测试与热部署功能。单元测试方面,通过JUnit和Mockito等工具,结合SpringBootTest注解,可以模拟真实环境对应用组件进行独立测试,验证逻辑正确性,提升代码质量。具体演示了HelloWorld01和H…

thinkphp+mysql+cast解决text类型字段的文本型数字排序错误的方法 - 数据库文本字段排序ASC、DESC的失效问题

TP中使用cast order $lists AmdCommonTable::where(..............) ->field(*,CAST(w6 AS UNSIGNED) as sort) ->order(sort, asc) ->select() ->toArray(); 先转换为数字,再order by 效果对比 (1/2) 不ok - 直接order by 某字段 asc - 只能按照文本…

批量将 Excel 转换 PDF/Word/CSV以及图片等其它格式

Excel 格式转换是我们工作过程当中非常常见的一个需求,我们通常需要将 Excel 转换为其他各种各样的格式。比如将 Excel 转换为 PDF、比如说将 Excel 转换为 Word、再比如说将 Excel文档转换为图片等等。 这些操作对我们来讲都不难,因为我们通过 Office 都…

C语言每日一练——day_3(快速上手C语言)

引言 针对初学者,每日练习几个题,快速上手C语言。第三天。(会连续更新) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用…

RSA的理解运用与Pycharm组装Cryptodome库

1、RSA的来源 RSA通常指基于RSA算法的密码系统,令我没想到的是,其名字的来源竟然不是某个含有特别意义的单词缩写而成(比如PHP:Hypertext Preprocessor(超文本预处理器)),而是由1977年提出该算法的三个歪果…

聊一聊 Android 的消息机制

聊一聊 Android 的消息机制 侯 亮 1 概述 在 Android 平台上,主要用到两种通信机制,即 Binder 机制和消息机制,前者用于跨进程通信,后者用于进程内部通信。 从技术实现上来说,消息机制还是比较简单的。从大的方面讲…

数据结构第八节:红黑树(初阶)

【本节要点】 红黑树概念红黑树性质红黑树结点定义红黑树结构红黑树插入操作的分析 一、红黑树的概念与性质 1.1 红黑树的概念 红黑树 ,是一种 二叉搜索树 ,但 在每个结点上增加一个存储位表示结点的颜色,可以是 Red和 Black 。 通过对 任何…

CI/CD—Jenkins配置一次完整的jar自动化发布流程

背景: 实现设想: 要创建自动化发布,需要准备一台测试服务器提前安装好java运行所需的环境,JDK版本最好和Windows开发机器上的版本一致,在Jenkins上配置将构建好的jar上传到测试服务器上,测试服务器自动启动…

我的两个医学数据分析技术思路

我的两个医学数据分析技术思路 从临床上获得的或者公共数据库数据这种属于观察性研究,是对临床诊疗过程中自然产生的数据进行分析而获得疾病发生发展的规律等研究成果。再细分,可以分为独立危险因素鉴定和预测模型构建两种。 独立危险因素鉴定是一直以…

时序数据库TimescaleDB基本操作示例

好的&#xff01;以下是使用 TimescaleDB 的 Java 示例&#xff08;基于 JDBC&#xff0c;因为 TimescaleDB 是 PostgreSQL 的扩展&#xff0c;官方未提供独立的 Java SDK&#xff09;&#xff1a; 1. 添加依赖&#xff08;Maven&#xff09; <dependency><groupId&g…

HTML-网页介绍

一、网页 1.什么是网页&#xff1a; 网站是指在因特网上根据一定的规则&#xff0c;使用 HTML 等制作的用于展示特定内容相关的网页集合。 网页是网站中的一“页”&#xff0c;通常是 HTML 格式的文件&#xff0c;它要通过浏览器来阅读。 网页是构成网站的基本元素&#xf…

Mybatis 的关联映射(一对一,一对多,多对多)

前言 在前面我们已经了解了&#xff0c;mybatis 的基本用法&#xff0c;动态SQL&#xff0c;学会使用mybatis 来操作数据库。但这些主要操作还是针对 单表实现的。在实际的开发中&#xff0c;对数据库的操作&#xff0c;常常涉及多张表。 因此本篇博客的目标&#xff1a;通过my…

vue3通过render函数实现一个菜单下拉框

背景说明 鼠标移动到产品服务上时&#xff0c;出现标红的下拉框。 使用纯css的方案实现最简单&#xff0c;但是没什么技术含量&#xff0c;弃之&#xff1b;使用第三方组件库&#xff0c;样式定制麻烦弃之。因此&#xff0c;我们使用vue3直接在页面创建一个dom作为下拉框吧。…

Docker介绍和安装

跨平台快速运行应用快速构建应用快速分享应用 docker是用来加速,构建,分享,运行的容器 在 Docker 的架构中&#xff0c;Client、Docker Host 和 Registry 是三个核心组成部分&#xff0c;它们各自承担不同的功能和作用。以下是对这三部分的详细描述&#xff1a; Docker的基本…

nnMamba:基于状态空间模型的3D生物医学图像分割、分类和地标检测

摘要 本文提出了一种基于状态空间模型&#xff08;SSMs&#xff09;的创新架构——nnMamba&#xff0c;用于解决3D生物医学图像分割、分类及地标检测任务中的长距离依赖建模难题。nnMamba结合了卷积神经网络&#xff08;CNN&#xff09;的局部特征提取能力与SSMs的全局上下文建…

elasticsearch商业产品

Elasticsearch商业产品介绍 在当今数字化时代&#xff0c;数据如同石油一样珍贵。而要从海量的数据中提取有价值的信息&#xff0c;则需要强大的工具。这就是Elasticsearch商业产品的用武之地。Elasticsearch是一款开源的搜索引擎&#xff0c;它能够快速地存储、搜索和分析大规…