Compact行记录

​ InnoDB存储引擎和大多数数据库一样,记录是以行的形式存储的。这就意味着页中保存着表中一行行的数据。在InnoDB 1.0x版本之前,InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录数据。Redundant格式是为了兼容之前版本而保留的(mysql5.0版本之前InnoDB的行记录存储方式)。源码中使用PHYSICAL RECORD (NEW STYLE) 和PHYSICAL RECORD (OLD STYLE)来区分两种格式的。在mysql5.1版本中,默认设置为Compact行格式。可以通过命令SHOW TABLES STATUS LIKE ‘表名’ 来查看当前表使用的行格式,其中row_format属性表示当前所使用的行记录结构类型。

Compact行记录的设计目标是高效地存储数据。简单来说,一个页存放的行数据越多,其性能就越高。Compact行记录的存储方式如下:

在这里插入图片描述

从图中可以看出:

  1. Compact行记录格式的首部是一个非NULL变长字段长度列表,并且其是按照列的顺序逆序放置的,其长度为:

    • 若列的长度小于255字节,用1字节表示;
    • 若列长度大于255个字节,用2字节表示。

    变长字段的长度最大不可以超过2字节,这是因为在mysql数据库中VARCHAR类型的最大长度限制为65535。

  2. NULL标志位,指示了该行数据中是否有NULL值,有则用1表示;

  3. 记录头信息,固定占用5字节(40位),每位的含义如下:在这里插入图片描述

  4. 最后的部分就是实际存储每个列的数据。

注:

  • NULL不占该部分任何空间,即除了占有NULL标志位,实际存储不占有任何空间
  • 每个数据行除了用户定义的列外。还有两个隐藏列,事务ID列和回滚指针列,分别为6字节和7字节大小
  • InnoDB 表没有定义主键,每行还会增加一个6字节的rowid列

接下来会用一个具体的示例来分析Compact行记录的内部结构:

CREATE TABLE `mytest` (
`t1` varchar(10) DEFAULT NULL,
`t2` varchar(10) DEFAULT NULL,
`t3` char(10) DEFAULT NULL,
`t4` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT;

插入三条数据:

mysql> select * from mytest;
+------+------+------+------+
| t1 | t2 | t3 | t4 |
+------+------+------+------+
| a | bb | bb | ccc |
| d | ee | ee | fff |
| d | NULL | NULL | fff |
+------+------+------+------+

打开表空间文件mytest.ibd,内容如下:

在这里插入图片描述

该行记录从0000c078开始(第一行)

03 02 01 /*变长字段长度列表,逆序*/
00 /*NULL标志位,第一行没有NULL值*/
00 00 10 00 2C/*Record Header,固定5字节长度*/
00 00 00 2B 68 00/*RowID InnoDB自动创建,6字节*/
00 00 00 00 06 05/*TransactionID*/
80 00 00 00 32 01 10/*Roll Pointer*/
61/*列1数据 'a' */
62 62/*列2数据 'bb' */
62 62 20 20 20 20 20 20 20 20/*列3数据 'bb' */
63 63 63/*列4数据 'ccc' */

首先变长字段是逆序的,因此变长字段长度列表为 03 02 01,而不是01 02 03。可以看到,固定长度CHAR字段在未能完全占用其长度空间时,会用0x20来进行填充。

Rocord Header的最后两个字节next_recorder,0x2c代表下一个记录的偏移量,即当前记录的位置加上偏移量0x2c就是下一条记录的起始位置。所以InnoDB引擎在页内部是通过一种链表的结构来串联各个行记录的。

有NULL值得第三行:

03 01 /*变长字段长度列表,逆序*/
06 /*NULL标志位,第一行没有NULL值*/
00 00 20 ff 98/*Record Header,固定5字节长度*/
00 00 00 2b 68 00/*RowID InnoDB自动创建,6字节*/
00 00 00 00 06 07/*TransactionID*/
80 00 00 00 32 01 10/*Roll Pointer*/
64/*列1数据 'a' */
66 66 66/*列4数据 'fff' */

第三行有NULL值,因此NULL表示为不再是00 而是06,转成二进制位00000110,为1的值代表第2列和第3列的数据为NULL。可以发现,第三行只存储了第1列和第4列非NULL的值。

与Redundant行记录格式相比:
不管是CHAR类型还是VARCHAR类型,在Compact格式下NULL值都是不占用任何存储空间的
对于VARCHAR类型的NULL值,Redudant行记录格式同样不会占用任何存储空间,而CHAR类型的NULL值需要占用空间

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值