InnoDB记录存储结构
记录:就是一条信息
不同的存储引擎的记录存储结构是不一样的。
假如:
每次存取数据都是一条一条的,那么就很浪费时间。
所以:
将数据分为若干的页存储,每次存取都直接读一页,一页InnoDB默认的大小16KB
存放数据(一条记录)的格式:compact、redundant、dynamic、compressed
create table 表名 (列信息) row_format=行格式名称 alter table 表名 row_format=行格式名称
COMPACT行格式
变长字段长度列表
变长字段:varchar、varbinary、text、blob
把所有变长字段的真实数据占用的字节长度都存放在变长字段长度列表,各变长字段数据占用的字节数按照列的顺序逆序存放;
例如:
create table demo( c1 varchar(10), c2 varchar(10) not null, c3 char(10), c4 varchar(10) ) charset=ascii row_fromat=compact;
insert into demo(c1, c2, c3, c4) values(‘aaaa‘, ‘bbb‘, ‘cc‘, ‘d‘), (‘eeee‘, ‘fff‘, null, null);
第一条数据:c3的char不是变长
列名 | 存储内容 | 内容长度 | 内容长度 |
c1 | ‘aaaa‘ | 4 | 0x4 |
c2 | ‘bbb‘ | 3 | 0x03 |
c4 | ‘d‘ | 1 | 0x01 |
所以变长字段长度列表为,注意是逆序的
可看出:变长字段长度列表是:3个字节表示;每一个字段用一个字节表示就行了
但是什么时候用两字节表示呢:
如果可变字段允许存储的最大字节数超过255,并且真实存储的字节数超过127字节,那么使用两个字节,否则用1个字节
null值列表:
还是上述demo,c1、c3、c4可以为null,因为c2不可以为null,not null
对于第一条数据,没有null值
对于第二条数据:c3和c4都为null,所以值为1
假如一个表的可以为nul的字段超过了一个字节,那就用两个字节,反正高位补0??
记录头信息
名称 | 大小 | 描述 |
预留位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 | 表示下一条记录的相对位置 |
记录的真实数据
假如表没有指定主键,则选取一个unique键作为主键,如果表中连unique键也没有指定,那么会innoDB会送一个row_id作为隐藏的主键。如果设置了主键,那当我没说
列名 | 是否必须 | 占用空间 | 描述 |
row_id | 否 | 6字节 | 送的主键,表有就不送 |
transaction_id | 是 | 6字节 | 送的事务ID |
roll_pointer | 是 | 7字节 | 送的回滚指针 |
Redundant格式
字段长度偏移表:
还是上面的例子;
row_id:6 0x06
transaction:12 0x0c
roll_pointer:19 0x13
c1:23 0x17
c2:26 0x1A
c3:36 0x24
c4:37 0x25
所以字段长度偏移列表:
0x25 0x24 0x1A......0x06
记录头信息
没必要那么深究了
关于varchar行溢出
compact、redundant,会存储该字段的前768个字节,用20字节指向其他的存储页
dynamic和compressed:不会在该记录中存储,直接指向其他存储页面。