关于mysql:验证一个小小的问题

7次阅读

共计 1818 个字符,预计需要花费 5 分钟才能阅读完成。

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

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

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

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

存储空间

先回顾一下之前的常识。

数据库中的一行记录在最终磁盘文件中也是以行的形式来存储的,对于 InnoDB 来说,有 4 种行存储格局:REDUNDANTCOMPACTDYNAMICCOMPRESSED

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 的。

可变字段长度列表 c1c3字段值长度别离为 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 的,所以他的这个测试无法说明咱们要验证的问题。

依照网上大佬给出的计划,创立表,而后插入测试数据,数据库中存在 NULL 值。

 CREATE TABLE test (c1 VARCHAR ( 32),
   c2 VARCHAR (32),
   c3 VARCHAR (32),
   c4 VARCHAR (32) ) ENGINE = INNODB row_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 个字节

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

 CREATE TABLE test (c1 VARCHAR ( 32) NOT NULL,
   c2 VARCHAR (32) NOT NULL,
   c3 VARCHAR (32) NOT NULL,
   c4 VARCHAR (32) NOT NULL ) ENGINE = INNODB row_format = compact;

拿到另外一个 ibd 文件。

比照其实很分明能发现问题,这时候曾经没有了 NULL 值列表的标记位了。

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

伟人的肩膀:

http://mysql.taobao.org/month…

https://www.cnblogs.com/zhouj…

正文完
 0