验证一个小小的问题

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

问题是这样的: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/monthly/2016/08/07/
https://www.cnblogs.com/zhoujinyi/archive/2012/10/17/2726462.html

Original: https://www.cnblogs.com/ilovejaney/p/16662461.html
Author: 艾小仙
Title: 验证一个小小的问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/608826/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Seata-初体验以及避坑

    Seata是什么 这里引用官方解释 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 …

    Java 2023年6月16日
    063
  • Java匿名内部类只可使用一次的理解

    匿名内部类只能使用一次,就不能在使用。 为了验证”只能使用一次”的实际含义,首先在程序中实例化了两个对象。并且在相应的类中加入了实现接口的匿名内部类: pa…

    Java 2023年6月9日
    066
  • springSecurity + OAuth2 获取Token流程分析以及增加协议授权模式

    springSecurity + OAuth2 获取Token流程分析以及增加协议授权模式 一、什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前…

    Java 2023年5月29日
    069
  • VS Code常用插件

    VS Code常用插件 一、插件的下载 打开VScode之后点击右侧带有小方块的图标在上方的输入框中输入想要下载的插件的名称即可 二、插件的种类 Chinese (Simplifi…

    Java 2023年6月13日
    086
  • 一文了解Docker基本概念

    一、何为Docker Docker 是一个用于开发、交付和运行应用程序的开放平台,Docker 使您能够将应用程序与基础环境分开,以便您可以快速交付软件。借用百度百科的话来说,Do…

    Java 2023年6月16日
    071
  • java技术难点

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年5月29日
    080
  • 实战派 | Java项目中玩转Redis6.0客户端缓存!

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处。 哈喽大家好啊,我是Hydra。 在前…

    Java 2023年6月5日
    090
  • 逃逸分析(Escape Analysis)详解

    概念说明 逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的…

    Java 2023年6月16日
    073
  • Java并发编程艺术系列-二、Java并发机制底层原理

    二、Java并发机制底层原理 volatile synchronized 原子操作 2.1 volatile原理与应用 2.1.1 特点 轻量级的 synchronized 共享变…

    Java 2023年6月9日
    093
  • 1.Spring jar包依赖

    <dependency> <groupid>commons-cli</groupid> <artifactid>commons-cl…

    Java 2023年6月13日
    089
  • 如何把Spring学精通了?

    作为 Java 后端工程师,几乎都要用到 Spring,今天这篇文章是和大家说说如何学好 Spring。 在之前的一篇 Java 读书路线的文章中,我介绍过 Spring 的读书路…

    Java 2023年6月7日
    058
  • Mybatis介绍、使用IDEA快速入门

    创建mybatis-demo模块,在pox.xml中添加mybatis的 依赖坐标 org.mybatis mybatis 3.5.5 mysql mysql-connector-…

    Java 2023年6月14日
    059
  • Hexo 博客部署至腾讯云

    一.安装环境 推荐购买腾讯云活动的轻应用服务器 2C2G 就可以啦,我买的是 45 一年的:点我购买 以下命令默认在 ubuntu 系统上执行 安装 nginx apt-get i…

    Java 2023年6月8日
    078
  • 工厂模式-理解Spring的Bean工厂(马士兵经典例子)

    工厂模式-理解Spring的Bean工厂 接面向对象里面 “老张开车去东北”的场景。链接名称 封装”老张开车去东北”里面的交通工具,…

    Java 2023年5月30日
    078
  • 游戏协议安全测试

    测试人员通过第三方工具篡改游戏客户端发送给服务器的协议,达到测试服务器逻辑、挖掘游戏漏洞的一种测试行为,称之为游戏协议安全测试。 协议测试的作用是测试服务器逻辑的漏洞,避免游戏上线…

    Java 2023年6月5日
    0121
  • java中使用ReentrantLock实现线程安全

    如下代码: class Window4 implements Runnable { private int ticket=100; //1、先定义一个变量 private Reen…

    Java 2023年5月29日
    061
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球