以 MySQL 默认的存储引擎 InnoDB 为例
InnoDB 包含如下四种行格式html
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称; ALTER TABLE 表名 ROW_FORMAT=行格式名称;
示例:
建立一张表,指定行格式为 Compact算法
CREATE TABLE test_table ( c1 VARCHAR(10), c2 VARCHAR(10) NOT NULL, c3 CHAR(10), c4 VARCHAR(10) CHARSET=ascii ROW_FORMAT=COMPACT;
Compact 中一条完整的记录能够被分红 '记录的额外信息' 和 '记录的真实数据' 两部分sql
Compact 中记录的额外信息包含三类:变长字段长度列表、NULL 值列表、记录头信息指针
MySQL 支持一些变长的数据类型 (VARCHAR),这些数据在存储时不只要存储数据内容,还须要将占用的字节数存储起来
定长数据类型 (CHAR) 在以一些变长字符集储存数据时,因为储存长度为变长,因此也须要在该列表中存储其长度
在记录的开头部位就是各个变长字段占用的字节数,这些数据逆序存放
若是表中没有变长字段,就没有变长字段长度列表code
NULL 值列表存储有表中全部 NULL 值,能够节约许多空间
值为 1 时,表明 NULL;值为 0 时,表明非 NULL。当位数不够整数个字节的时候,在高位补 0
全部数据逆序存放
若是表中没有容许储存 NULL 值的列,就没有 NULL 值列表htm
名称 | 大小 (bit) | 描述 |
---|---|---|
预留位1 | 1 | 没有使用 |
预留位2 | 1 | 没有使用 |
delete_mask | 1 | 标记该记录是否被删除 |
min_rec_mask | 1 | B+树的每层非叶子节点中的最小记录都会添加该标记 |
n_owned | 4 | 表示当前记录拥有的记录数 |
heap_no | 13 | 表示当前记录在记录堆的位置信息 |
record_type | 3 | 表示当前记录的类型,0 表示普通记录,1 表示B+树非叶子节点记录,2 表示最小记录,3 表示最大记录 |
next_record | 16 | 表示下一条记录的相对位置 |
除了一些自定义列的数据外,MySQL 还会为每一个记录默认添加一些隐藏列:blog
列名 | 是否必须 | 占用空间 (bit) | 描述 |
---|---|---|---|
DB_ROW_ID | 否 | 6 | 行ID,惟一标识一条记录 |
DB_TRX_ID | 是 | 6 | 事务ID |
DB_ROLL_PTR | 是 | 7 | 回滚指针 |
只有当用户没有指定主键,且表中没有 Unique 键时才会添加 DB_ROW_ID
做为主键事务
当定长数据类型 (CHAR) 没有储存满时,剩下的位都由空格 (0x20) 填满
当使用变成字符集时,因为储存字节长度不必定,当占用字节数少的字符串变为占用字节数多的字符串时须要新开辟一个空间,会产生存储碎片ci
Redundant 行格式会把该条记录中全部列 (包括隐藏列) 的长度信息都按照逆序存储到 '字段长度偏移列表' 中
储存的值为两个相邻数值的差值
全部数据逆序存放字符串
名称 | 大小 (bit) | 描述 |
---|---|---|
预留位1 | 1 | 没有使用 |
预留位2 | 1 | 没有使用 |
delete_mask | 1 | 标记该记录是否被删除 |
min_rec_mask | 1 | B+树的每层非叶子节点中的最小记录都会添加该标记 |
n_owned | 4 | 表示当前记录拥有的记录数 |
heap_no | 13 | 表示当前记录在页面堆的位置信息 |
n_field | 10 | 表示记录中列的数量 |
1byte_offs_flag | 1 | 标记字段长度偏移列表中每一个列对应的偏移量是使用1字节仍是2字节表示的 |
next_record | 16 | 表示下一条记录的相对位置 |
无论该列使用的字符集是什么,只要是使用 CHAR 类型,占用的真实数据空间就是该字符集表示一个字符最多须要的字节数和字符串长度
例如使用 utf8 字符集的 CHAR(10) 列占用的真实数据空间始终是 30 个字节
MySQL 8.0 中默认的行格式为 Dymatic
这两个行格式与 Compact 只有在处理行溢出数据 (<- 点击查看) 时有不一样:它们不会在记录真实数据处储存真实数据的前 768 个字节,而是把全部的字节都存储到其余页面中,而且只储存其余页面的地址 Compressed 与 Dymatic 不一样的一点是它会采用压缩算法对页面进行压缩,以节省空间