首页 火币pro官网下载文章正文

验证一个小小的问题

火币pro官网下载 2022年10月21日 11:02 110 Connor

关注

“脚本之家

”,与百万开发者在一起

本文经艾小仙(id:aixiaoxianren)授权转载

如若转载请联系原公众号

在之前的文章提到过一个问题,而且网上很多文章也是这么说的,前几天有人对这个问题提出了一点不同的意见,抱着谨慎的态度做了一个测试。

问题是这样的:COMPACT格式下,NULL值列表是否一定会占用一个字节的空间?

对于这个问题,我的回答和网上很多回答是一样的,如果都是NOT NULL就不会有NULL值列表,所以不会占用,反之则会占用。

今天,就对这个问题做一个验证。

存储空间

先回顾一下之前的知识。

数据库中的一行记录在最终磁盘文件中也是以行的方式来存储的,对于InnoDB来说,有4种行存储格式: REDUNDANT 、 COMPACT 、 DYNAMIC 和 COMPRESSED 。

InnoDB的默认行存储格式是 COMPACT ,存储格式如下所示,虚线部分代表可能不一定会存在。

变长字段长度列表:有多个字段则以逆序存储,我们只有一个字段所有不考虑那么多,存储格式是16进制,如果没有变长字段就不需要这一部分了。

NULL值列表:用来存储我们记录中值为NULL的情况,如果存在多个NULL值那么也是逆序存储,并且必须是8bit的整数倍,如果不够8bit,则高位补0。1代表是NULL,0代表不是NULL。如果都是NOT NULL那么这个就存在了,每多8个NULL会多占用一个字节的空间。

ROW_ID:一行记录的唯一标志,没有指定主键的时候自动生成的ROW_ID作为主键。

TRX_ID:事务ID。

ROLL_PRT:回滚指针。

最后就是每列的值。

为了说明清楚这个存储格式的问题,我弄张表来测试,这张表只有 c1 字段是NOT NULL,其他都是可以为NULL的。

展开全文

可变字段长度列表: c1 和 c3 字段值长度分别为1和2,所以长度转换为16进制是 0x01 0x02 ,逆序之后就是 0x02 0x01 。

NULL值列表:因为存在允许为NULL的列,所以 c2,c3,c4 分别为010,逆序之后还是一样,同时高位补0满8位,结果是 00000010 。

其他字段我们暂时不管他,最后第一条记录的结果就是,当然这里我们就不考虑编码之后的结果了。

这样就是一个完整的数据行数据的格式,反之,如果我们把所有字段都设置为NOT NULL,并且插入一条数据 a,bb,ccc,dddd 的话,存储格式应该这样:

测试

这里存在一点点小问题,首先我看到了阿里的数据库月报中的测试和描述。

从这段代码看出之前的猜想,也就是并不是Null标志位只固定占用1个字节==,而是以8为单位,满8个null字段就多1个字节,不满8个也占用1个字节,高位用0补齐

从这段代码看出之前的猜想,也就是并不是Null标志位只固定占用1个字节==,而是以8为单位,满8个null字段就多1个字节,不满8个也占用1个字节,高位用0补齐

他的意思是无论如何都会占用一个字节,但是看了他的测试,发现他的表是允许NULL的,所以他的这个测试无法说明我们要验证的问题。

按照网上大佬给出的方案,创建表,然后插入测试数据,数据库中存在NULL值。

CREATETABLEtest( c1 VARCHAR( 32),

c2 VARCHAR( 32),

c3 VARCHAR( 32),

c4 VARCHAR( 32) ) ENGINE= INNODBrow_format = compact;

使用命令 SHOW VARIABLES LIKE 'datadir' 找到 ibd 文件位置。

使用命令转换 ibd 文件为 txt 文件。

hexdump -C -v test.ibd > /Users/irving/test-null.txt

打开文件找到 supremum 部分。

不用看那么多,就看一部分:

03 02 02 01 是上面说的变长字段长度列表,以为我们有4个字段,所以4个字节。

00 就是NULL标志位

00 00 10 00 25 是数据头5个字节

03 02 02 01 是上面说的变长字段长度列表,以为我们有4个字段,所以4个字节。

00 就是NULL标志位

00 00 10 00 25 是数据头5个字节

这个肯定没有问题,然后再次创建一张表,这时候字段都是NOT NULL,然后再次执行命令。

CREATETABLEtest( c1 VARCHAR( 32) NOTNULL,

c2 VARCHAR( 32) NOTNULL,

c3 VARCHAR( 32) NOTNULL,

c4 VARCHAR( 32) NOTNULL) ENGINE= INNODBrow_format = compact;

拿到另外一个 ibd 文件。

对比其实很清楚能发现问题,这时候已经没有了NULL值列表的标志位了。

SO,这个测试结果证明,如果存在任意NULL值,NULL值列表至少占用一个字节的空间,以后每多8个NULL值多占用一个字节,如果都是NOT NULL,则不会存在NULL值列表标记,不占用空间。

巨人的肩膀:

/

/

<END>

程序员专属卫衣

商品直购链接

【☝?点击查看更多详情】

专属定制,程序员秒懂的极客卫衣!

为什么阿里巴巴禁止数据库中做多表join?

美团三面:一直追问我, MySQL 幻读被彻底解决了吗?

什么?你还不会安装MySQL

Mysql的索引为什么使用B+树而不使用跳表?

Office 2019/2021专业增强版,正版终身授权!

发表评论

火币交易所(huobi) | 火币全球站官网入口 备案号:川ICP备66666666号