InnoDB行格式
InnoDB是一个将表中的数据存储到磁盘上的存储引擎。 为了方便磁盘与内存的读取,InnoDB以页的格式存储数据。我们可以通过 SHOW GLOBAL VARIABLES LIKE 'innodb_page_size';
的方式查看页的大小。 一般来说,页的大小会设置为16384(16KB)。
我们以记录为单位向表中插入数据。 这些记录在磁盘存储的格式称为行格式或者纪录格式。 我们可以通过下面的方式指定或者修改表的行格式:
CREATE TABLE (TABLE NAME) (COLUMN INFORMATION) ROW_FORMAT=();
ALTER TABLE (TABLE NAME) ROW_FORMAT=();
行格式主要有四类:
- COMPACT
- REDUNDANT
- DYNAMIC
- COMPRESSED
COMPACT行格式
我们主要以COMPACT为例讲解。COMPACT行格式记录的信息包括记录的额外信息和记录的真实数据两部分,可以表示为
变长字段长度列表,NULL值列表,记录头信息 (额外信息)
列1的信息,列2的信息,……,列n的信息 (真实数据)
记录的额外信息
变长字段长度列表
顾名思义,这块主要以列表形式存储诸如VARCHAR(M), VARBINARY(M)
,各种TEXT
类型,各种BLOB
类型这样的变长数据类型数据的字节数。各变长字段的真实数据占用的字节数按照列的顺序逆序存放。
那么如何确定表的最大长度呢?第一步一定是首先查看表结构,并确定某个变长字段运行存储的最大字节数。 之后比较理论最大字节数(即最多存储的字符数 × 字符集单字符最多需要的字节数)与允许的最大字节数进行比较。 如果超过且真实数据占用的字节超过允许最大字节数\2,那么用2字节表示真实数据占用的字节数。否则使用1字节。
注意:变长字段长度列表中只存储值为非NULL的列的内容长度。 同时,行格式里不是一定要有变长字段长度列表。 比如表中没有变长数据类型或者有但都为NULL,则不需要该列表。
NULL值列表
COMPACT行格式会把表中值为NULL的列统一管理,其过程如下:
1、 统计表中允许存储NULL的列。比如主键列以及用NOT NULL
修饰的列是不允许存储NULL值的。 如果表中没有允许存储NULL的列,那么NULL值表就不存在了。
2、 对允许存储NULL值的列对应一个二进制位。 同样, 二进制位按照列的顺序逆序排序。二进制位的意义位:
- 二进制位为1时, 代表该列的值为NULL
- 二进制位为0时, 代表该列的值不为NULL
3、 NULL值列表必须以整数字节表示,如果非整需要采用高位补零。
记录头信息
记录头信息有5个字节(40个二进制位),用于描述记录的一些属性。
记录的真实数据
除了表中的原始数据, MySQL还会位某些表默认添加一些列,也就是所谓隐藏列。
列名 | 是否必需 | 占用空间 | 描述 |
---|---|---|---|
DB_ROW_ID | 否 | 6字节 | 行ID, 唯一标识一条记录 |
DB_TRX_ID | 是 | 6字节 | 事务ID |
DB_ROLL_PTR | 是 | 7字节 | 回滚指针 |
DB_ROW_ID是针对如果用户没有指定主键列且也没有非NULL列(没有主键MySQL会选取一个不允许存储NULL的列作为主键)的情况下,MySQL会自动生成一个DB_ROW_ID列作为主键列。
REDUNDANT行格式
REDUNDANT行格式同样有两部分:
字段长度偏移列表, 记录头信息(额外信息)
列1的信息,列2的信息,……,列n的信息 (真实数据)
字段长度偏移列表
与变长字段长度列表相比:
- 所有列(包括隐藏列)的长度信息读按照逆序存储到字段长度偏移列表
- 采用两个相邻偏移量的差值来计算各个列值的长度
NULL值的处理
列对应的偏移量值的第一个比特位会标记该列是否位NULL,该比特位称为NULL比特位。
溢出列
页的大小一般是16KB,如果出现所需存取的数比页大小大的情况,就会出现所谓“溢出列”的现象。一般MySQL为了解决该问题,会把数据分散存在不同的页中。在行格式的真实数据处会用20字节存储指向这些页的地址。 MySQL规定一个页中至少存放两行记录。
标签:存储,段长度,字节数,列表,Innodb,格式,NULL From: https://www.cnblogs.com/wyfc4/p/17519820.html