MySQL系列(14)--Redundant行记录格式

Redundant是MySQL 5.0版本之前InnoDB的行记录存储方式,MySQL 5.0支持Redundant是为了向前兼容性。Redundant行记录以如下方式存储:

Redundant格式

从上图可以看到,不同于Compact行记录格式,Redundant行格式的首部是一个字段长度偏移列表,同样是按照列的顺序逆序放置的。当列的长度小于255字节,用1字节表示;若大于255个字节,用2个字节表示。第二个部分为记录头信息(record header),不同于Compact行格式,Redundant行格式固定占用6个字节(48位),每位的含义见表4-2。从表中可以看到,n_fields值代表一行中列的数量,占用10位,这也很好地解释了为什么MySQL一个行支持最多的列为1023。另一个需要注意的值为1byte_offs_flags,该值定义了偏移列表占用1个字节还是2个字节。最后的部分就是实际存储的每个列的数据了。
MySQL系列(14)--Redundant行记录格式_第1张图片
创建一张和mytest内容完全一样、但行格式为Redundant的表mytest2

create table mytest2 engine=innodb row_format=redundant as (select * from mytest);

show table status like ‘mytest2’\G

select * from mytest2\G

现在row_format变为Redundant。同样,通过hexdump将表空间mytest2.ibd导出到文本文件mytest2.txt。打开文件,找到类似如下行:

0000c070 08 03 00 00 73 75 70 72 65 6d 75 6d 00 23 20 16|……supremum.#.
0000c080 14 13 0c 06 00 00 10 0f 00 ba 00 00 00 2b 68 0b|……+h.
0000c090 00 00 00 00 06 53 80 00 00 00 32 01 10 61 62 62|……S……2..abb
0000c0a0 62 62 20 20 20 20 20 20 20 20 63 63 63 23 20 16|bb ccc#.
0000c0b0 14 13 0c 06 00 00 18 0f 00 ea 00 00 00 2b 68 0c|……+h.
0000c0c0 00 00 00 00 06 53 80 00 00 00 32 01 1e 64 65 65|……S……2..dee
0000c0d0 65 65 20 20 20 20 20 20 20 20 66 66 66 21 9e 94|ee fff!..
0000c0e0 14 13 0c 06 00 00 20 0f 00 74 00 00 00 2b 68 0d|……t……+h.
0000c0f0 00 00 00 00 06 53 80 00 00 00 32 01 2c 64 00 00|……S……2.,d..
0000c100 00 00 00 00 00 00 00 00 66 66 66 00 00 00 00 00|……fff……

整理可以得到如下内容:
20 16 14 13 0c 06/*长度偏移列表,逆序*/
00 10 0f 00 ba/*记录头信息,固定6个字节*/
00 00 2b 68 0b/*RowID*/
00 00 00 06 53/*TransactionID*/
00 00 00 32 01 10/*Roll Point*/
61/*列1数据'a'*/
62/*列2数据'bb'*/
62 20 20 20 20 20 20 20 20/*列3数据'bb'Char类型*/
63 63/*列4数据'ccc'*/

23 20 16 14 13 0c 06,逆转为06,0c,13,14,16,20,23。分别代表第一列长度6,第二列长度6(6+6=0x0C),第三列长度为7(6+6+7=0x13),第四列长度1(6+6+7+1=0x14),第五列长度2(6+6+7+1+2=0x16),第六列长度10(6+6+7+1+2+10=0x20),第七列长度3(6+6+7+1+2+10+3=0x23)。

记录头信息中应该注意48位中22~32位,为0000000111,表示表共有7个列(包含了隐藏的3列),接下去的33位为1,代表偏移列表为一个字节。

后面的信息就是实际每行存放的数据了,这与Compact行格式大致相同。

请注意是大致相同,因为如果我们来看第三行,会发现对于NULL的处理两者是不同的。

21 9e 94 14 13 0c 06/长度偏移列表,逆序/

00 00 20 0f 00 74/记录头信息,固定6个字节/

00 00 00 2b 68 0d/RowID/

00 00 00 00 06 53/TransactionID/

80 00 00 00 32 01 10/Roll Point/

64/列1数据’a’/

00 00 00 00 00 00 00 00 00 00/列3数据NULL/

66 66 66/列4数据’fff’/

这里与之前Compact行格式有着很大的不同了,首先来看长度偏移列表,我们逆序排列后得到06 0c 13 14 94 9e 21,前4个值都很好理解,第5个NULL变为了94,接着第6个列char类型的NULL值为9e(94+10=0x9e),之后的21代表14+3=0x21。可以看到对于varchar的NULL值,Redundant行格式同样不占用任何存储空间,因而char类型的NULL值需要占用空间。

当前表mytest2的字符集为Latin1,每个字符最多只占用1个字节。若这里将表mytest2的字符集转换为utf8,第三列char固定长度类型就不再是只占用10个字节了,而是10×3=30个字节,Redundant行格式下char固定字符类型将会占据可能存放的最大值字节数。

Compressed与Dynamic行记录格式
InnoDB Plugin引入了新的文件格式(file format,可以理解为新的页格式),对于以前支持的Compact和Redundant格式将其称为Antelope文件格式,新的文件格式称为Barracuda。Barracuda文件格式下拥有两种新的行记录格式Compressed和Dynamic两种。新的两种格式对于存放BLOB的数据采用了完全的行溢出的方式,在数据页中只存放20个字节的指针,实际的数据都存放在BLOB Page中,而之前的Compact和Redundant两种格式会存放768个前缀字节。

下图是Barracuda文件格式的溢出行:

MySQL系列(14)--Redundant行记录格式_第2张图片

Compressed行记录格式的另一个功能就是,存储在其中的行数据会以zlib的算法进行压缩,因此对于BLOB、TEXT、VARCHAR这类大长度类型的数据能进行非常有效的存储。

你可能感兴趣的:(MySQL)