这一章主要是讲记录的存储格式。
4-1
不同数据在不同存储引擎中的存储格式是不同的。
4-2
InnoDb引擎以页为单位与磁盘交互
4-3
记录的格式有四种,分别是
COMPACT REDUNDANT DYNAMIC COMPRESSED
指定语法是
CREATE TABLE 表名 (列的信息)ROW_FORMAT=格式名称;
核心 COMPACT格式
变长字段列表:
变长字段的真实数据占用的字节数都存放在开头位置,从而形成变长字段长度列表。
重要的是这个顺序是倒过来的。(为什么要倒着放下一章介绍)
一般来说,一个列占用的实际大小只需要一个字节就能描述了,但是有的列可能比较大,这就需要两个字节来描述这个列实际存储的数据的字节数。 具体用几个字节,要根据以下规则判断。
假设某字符编码最多用W字节表示一个字符
Varchar后面括号里的数字是M
该变长字段实际存储的字符串占用字节数是L
如果M*W <= 255 则用1字节表示实际存储的字符串占用的字节数
否则,如果L<=127用1个字节,>127用两个字节。
其实也就只有1字节和2字节这两种情况。如果某条记录存储的数据非常大的话,会用溢出页来存数据。
当然,变长字段列表也不是必须的。如果某个表里没有变长字段,那当然不需要这个表。
NULL值表
如果表中的列都不允许null值,则该段不存在。 如果有可以为null值的列,则会用bit位来标记是否为null值。1为该列是null,0为该列非null。 同样地,这一段段顺序也是和记录中列的顺序相反的。 此外,null段还会进行字节填充。
记录头信息
这个东西也不用记···看懂就行了。
额外的列
DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR 分别占用6、6、7字节。
DB_ROW_ID是没有列能做主键的时候出现的,用它做隐式主键。 第二个就是事务id,第三个就是回滚指针。见名知意了。
定长列char(m)
char(m)实际用的字节数也可能是不固定的。 比如utf8mb4编码,长度为10,10个字符最多占用40字节,最少占用10个字节。即使你放进去一个空字符串,也要花费10字节。 如果是ascii,则只会占用10字节。
这里要注意的是,如果是变长编码,如utf8mb4,则char(m)列实际占用的字节数也会记载到变长字段列表中。
REDUNDANT格式
没有null值表,把变长字段长度列表变成了字段长度偏移表。 当然,也是逆序的。
这里也设计一个问题,就是每个列的偏移量用1个字节还是2个字节表示。 这里的判断规则是
如果整个记录占用的字节数小于127,则1字节
大于127,小于32767,则2字节
更大的话,需要溢出页
因为没有null值表,所以需要把每个列偏移量字节的第一个比特位拿来做null值记录。 因此即使在127-255之间,也需要两个字节来表示。
对null值来说,如果对应的列是变长的,则不占用实际存储空间。如果对应的列是定长的,则用零字节填充。
对REDUNDANT格式下的定长列来说,也涉及到分配多少空间的问题。这里,REDUNDANT格式简单粗暴,直接给最大空间。 假设有一列是char(10),编码为utf8mb4,则直接分配40个字节。
溢出列
在COMPACT和REDUNDANT格式下,对于占用存储空间非常多的列,在记录的真实数据处只会存储部分数据,剩下的数据分散在其他的一些数据页中。在记录的真实数据处会用20字节指向这些页的地址。
DYNAMIC格式和COMPRESSED格式
5.7版本的默认格式是DYNAMIC。它与COMPACT基本一样,只是在存储溢出列的时候不存储768个字节的真实数据,只存储一个20字节的指针。 而COMPRESSED格式也大同小异,区别只是会对溢出页进行压缩。
|