行格式,也就是在页中,每行的记录如何存储。
在innodb中,行格式主要有4种。但是整体上,大同小异。
- 记录的额外信息这部分,是服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为
3
类,分别是变长字段长度列表、NULL
值列表和记录头信息 - 记录真实的数据。
todo💡
当然没怎么介绍记录头信息,后续有空填坑。
为什么要这么麻烦,有4种格式呢?本质上,还是为了尽可能减少行记录占的大小,这样每页就可以存储更多的数据。
这里处理的麻烦点,在于变长字段和NULL值处理。
行格式 | 字段长度处理 | 长度存储1个字节还是2个字节 | NULL值处理 | 溢出页处理 |
---|---|---|---|---|
REDUNDANT用的少了,早期使用 | 字段偏移长度偏移列表(重点,存储全部字段的偏移数据) | 判断整个记录真实数据的占用大小,<=127就使用1个字节。粒度大,是整行记录都用1个字节或者2个字节,而不是根据某些列来 | 偏移数据的最高位,标识是否为NULL,所以真实占用字节用1个字节还是2个字节,是判断<=127,因为最高位给了NULL值表示 | 真实数据前768字节 +20字节溢出页地址 |
COMPACT | 变长字段列表,会重复利用表定义,这里只存储变长的字段长度列表 | 结合表定义来决定,表定义最大1个字节,则直接用1个字节。否则真实数据<=127,则用1个字节,因为最高位用来判断,是1个字节还是2个字节。 | bitmap处理。将可能为NULL值的列表,通过Bitmap表示 | 真实数据前768字节 +20字节溢出页地址 |
DYNAMIC 默认行格式 | 和COMPACT一样 | 和COMPACT一样 | 只存储20字节的溢出页地址 | |
COMPRESSED 压缩版 | 和COMPACT一样 | 和COMPACT一样 | 只存储20字节的溢出页地址,并且主要是会对页边进行压缩 |
COMPACT行格式
变长字段列表 + NULL值列表 + 记录头信息。
技巧💡
针对变长字段,在额外信息中记录真实数据的占用字节数大小,来达到记录变长字节,而不是直接按最大字节来分配。
针对NULl值列表,我们可以通过bitmap来记录,当前值是否为NULL值。很明显,我们只需要记录可能为NULL的字段来生成NULL的bitmap即可。那哪些字段是可以为NULL值的?怎么判断?当时是在表结构定义的时候就已经知道了。
变长字段列表
NULL值处理(bitmap)
空值的处理,就比较简单。直接找出可能为空的列表,通过bitmap来存储。标识每个字符是否是空值。
- 主键列、被
NOT NULL
修饰的列都是不可以存储NULL
值的,所以在统计的时候不会把这些列算进去。比方说表test
的3
个列c1、c3、c4
都是允许存储NULL
值的,而c2
列是被NOT NULL
修饰,不允许存储NULL
值。 - 如果表中没有允许存储 NULL 的列,则 NULL值列表也不存在了,否则将每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列。二进制位的值为1时,代表该列的值为NULL,为0时,代表该列的值不为NULL。高位补0
REDUNDANT格式(已废弃)
了解了,COMPACT格式,REDUNDANT就很好理解了。首先,它也区分记录额外的信息和真实的数据2部分。
额外信息:
- 字段长度偏移列表
- 真实数据
和REDUNDANT比,很容易发现,他没有NULL值的bitmap.那他是如何处理NULL值的呢?
字段长度偏移列表
- 这里是字段长度,注意这里不像REDUNDANT,不是变长。意味着它会记录该条记录(包含隐藏列)的长度信息。所以才是他有点浪费。
- 记录的是偏移量,而不是具体的长度数据,不够直观。(怎么理解?)
- 第一列,长度是 20. 第二列,偏移量是30.那么第二列的长度是(30-20=10)。
NULL值处理。 高位表示
这里,没有使用COMPACT的方式,使用bitmap来表示,而是将偏移量的最高位,来作为是否为NULL值。
怎么判断是1个字节还是2个字节
(通过记录实际占用的字节数来判断,如果>127,则全部字节都使用2个字节来表示长度。在header中会有个标识,来记录是1个字节还是2个字节表示长度)
为什么是>127,就是2个字节?因为最高位给判断是否NULL的标识了
溢出页处理方式
保留真实数据的前768字节 + 20字节溢出页面地址
[DYNAMIC]
和COMPACT基本一样,但是对溢出页处理方式不一样。它记录的是20字节溢出页面地址,没有保留真实数据的前768个字节数据。
[COMPRESSED]
和DYNAMIC没什么不同,主要在于进行了数据压缩。
文章
MySQL的varchar水真的太深了——InnoDB记录存储结构_varchar存储结构_砖业洋__的博客-CSDN博客
MySQL :: MySQL 8.0 Reference Manual :: 8.4.7 Limits on Table Column Count and Row Size