mysql innodb 行格式,Mysql-InnoDB数据行格式

Mysql-InnoDB数据行格式

InnoDB页简介

InnoDB是一个将表中数据存储到磁盘的存储引擎,真正处理数据的过程是发生在内存中的,所以需要把磁盘中的数据加载到内存中。如果是处理写入或者修改请求的话还需要把内存中的内容刷新到磁盘上。读写磁盘的速度是非常慢的,和内存读写差了几个数量级,所以当我们想从表中获取某些记录的时候,InnoDB存储引擎不是将记录一条一条从磁盘中读取出来的,那样会很慢。InnoDB采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,页的大小一般为16KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB刷新到磁盘中。

InnoDB行格式

平时是以记录为单位来想表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式或者记录格式。有4种不同类型的行格式。(Compact,Redundant,Dynamic,Compressed)

指定行格式的语法CREATE TABLE damei (列的信息) ROW_FORMAT=行格式名称(Compact)ALTER TABLE 表名 ROW_FORMAT=行格式名称

接下来重点记录一下 Compact行格式

c7b0ed1773630a83efd6057355a63371.png

引入一张图来表示

分为两大部分记录的额外信息和记录的真实数据(其实还有隐藏字段)

记录的额外信息

这部分信息是服务器为了描述这条记录而添加的信息,这些额外信息分为3类变长字段长度列表,NULL值列表和记录头信息。

变长字段长度列表

Mysql支持一些变长数据类型,比如varchar(M),以及各种TEXT类型,各种BLOB类型。可以将这些数据类型的列称为变长字段,变长字段中存储多少字节的数据是不固定的,索引在存储真是数据的时候需要把这些数据占用的字节数也存起来。这些变长字段占用的存储空间分为两部分:真正的数据内容

占用的字节数

在Compact行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表,各变长字段数据占用的字节数按照列的顺序逆序存放

有的列的字符串比较短,占用字节数比较小,用一个字节可以表示,有的变长列内容占用字节数比较多,可能需要2个字节来表示。具体用一个字节还是2个字节来表示真实数据占用的字节数,InnoDB有一套规则。用W、M 和 L来表示。假设某个字符集中表示一个字符最多需要使用的字节数为W,也就是SHOW CHARSERT 语句中的 Maxlen列,比如 utf8字符集中的W是3,gbk是2,ascii是1。

对于变长类型 varchar(M),这种类型表示能存储最多M个字符。(是字符不是字节) 所以这个类型能表示的字符串最多占用的字节数就是M✖️W

假设它实际存储的字符串占用的字节数是L。

所以确定使用是1个字节还是2个字节表示真正字符串占用的字节数的规则:如果**M✖️W <= 255 ** 那么使用1个字节来表示真正字符串占用的字节数。也就是说在InnoDB在读记录的变长字段长度列表时先查看表结构,如果某个变长字段允许存储的最大字节数不大于255时,可以认为只使用一个字节来表示真正字符串占用的字节数。如果 M✖️W > 255 则分为两种情况:L <= 127 ,则用1个字节来表示真正字符串占用的字节数。

L > 127 ,则用2个字节来表示真正字符串占用的字节数。

另外需要注意的一点是,变长字段长度列表中只存储值为 非NULL 的列内容占用的长度,值为 NULL 的列的长度是不储存的 。

NULL值列表

某些列中可能存储NULL值,Compact行格式把这些值为NULL的列统一管理起来,存储到NULL值列表中,它的处理过程是这样的:首先统计表中允许存储NULL的列有哪些

如果表中没有允许存储NULL的列,则NULL值列表也不存在了,否则将每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列。二进制位的值为1时,代表该列的值为NULL。

二进制位的值为0时,代表该列的值不为NULL。

记录头信息

除了变长字段长度列表、NULL值列表之外,还有一个用于描述记录的记录头信息,它是由固定的5个字节组成。5个字节也就是40个二进制位,不同的位代表不同的意思

找一张图来表示

690841103578138f1e06ace41b87e9fd.png下一次学习记录中解释这些记录头信息,现在在写这篇博客的时候已经对这些配置了解的7788了

记录真实数据

之前说了 除了这3个额外信息还有隐藏列,分别是 row_id -> 占用空间:6字节 -> 行ID,唯一表示一条记录(在没有主键的情况下)

transaction_id -> 占用空间:6字节 -> 事务ID

roll_pointer -> 占用空间:7字节 ->回滚指针

CHAR(M)列的存储格式

char(M)是一个定长字符列,如果采用ascii确实是定长的,但是如果是gbk or utf8那么就会变成变长字符列,也会存储到变长字段长度列表中。变长字符集的CHAR(M)类型的列要求至少占用M个字节,而VARCHAR(M)却没有这个要求。比方说对于使用utf8字符集的CHAR(10)的列来说,该列存储的数据字节长度的范围是10~30个字节。即使我们向该列中存储一个空字符串也会占用10个字节,这是怕将来更新该列的值的字节长度大于原有值的字节长度而小于10个字节时,可以在该记录处直接更新,而不是在存储空间中重新分配一个新的记录空间,导致原有的记录空间成为所谓的碎片。

最后现在mysql8.0默认的是行格式为 Dymatic 和 本文中介绍的处理方式都是一样的不过在处理行溢出不一样 不过这都是之后要学习记录的内容了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值