Mysql一行记录存储过程
Mysql的文件架构
行(row)
数据库表中的记录都是行存放的,每行继续根据不同的行格式都有不同的存储结构。
页(page)
记录是按照行来存储的,但是数据库的读取是以页为单位的,也就是我们读一条数据,不是将这个数据从磁盘读取出来而是以页为单位,然后写入缓存,一个页的数据大小都是16kb
区(extent)
B+tree每一层都是用双向脸部连接的, 可能两个页相隔特别远。可能不是内存连续的。所以一个区包含多个页
段(segment)
表空间由各个段组成,因为段不是内存连续的,段一般分为数据段(主键树)、索引段(索引树)、回滚段。
INNODB Compact行格式
行格式分为记录额外信息和记录真实数据。
记录额外信息
**记录额外信息:**变长字段长度列表、NULL值列表、记录头信息
变长字段长度列表
varchar和char相比,char是定长度,而varchar是变长的,变长字段是寄存处的数据长度(大小)不固定。
所以有了变长字段长度列表再去获取变长字段的时候就可以读取对应长度的数据。
可变长字段长度列表是逆序存放的,比如存放的内容是03 01而不是01 03,如果为null不会存放
图片来自xiaolin coding
为什么选择倒序存放
这个设计是有想法的,主要是因为「记录头信息」中指向下一个记录的指针,指向的是下一条记录的「记录头信息」和「真实数据」之间的位置,这样的好处是向左读就是记录头信息,向右读就是真实数据,比较方便。
因为可以让我们一个页中的靠前的真实记录的数据和数据丢赢的字段长度信息可以同时在同义词CPU Cache line中,可以提高我们CPU Cache的命中率。
NULL值列表
表中有一些列可能存放null值,但是把null值存入进去是比较浪费空间的,所以Compact行把这些值为null的存储到Null值列表中。
如果二进制位的值为1,那么该值为NULL,
如果二进制的值值为0,那么该值不为NULL
NULL值列表必须用整个字节的位表示(1字节8位),二进制个数不足高位补0
图片来自xiaolin coding
最后转换为16进制是0x04
如果是
那么最后的的结果为0x004
每个字段都有NULL值列表吗?
不是的,如果我们所有的字段就是NOT NULL就不会有,这样可以节省至少1字节。
记录头信息
**delete_mask:**删除标记
我们执行delete删除语句不会立刻从硬盘上删除,而是在INNODB的行结构COMpact的delete_mask进行标记,然后直到等待INNODB后来线程负责清理。这个做的原因是INNODB的一种优化策略叫做延迟删除,有助于提高性能和减少硬盘碎片。
recored_type: 表示当前记录的类型 0位普通记录(真实数据也可能是主键),1为非叶子结点记录(也可能是真索引也可能是主键),2为最小记录,3表示最大记录。
记录的真实数据
row_id
如果我们有主键或者唯一约束列那么久就没有row_id.如果没有row_id隐藏字段,那么久就是没指定主键和唯一约束,