(1)为什么一行数据里的NULL值不能直接存储?
    假设这个字段的NULL值在我们磁盘上存储的时候,就是按照“NULL”这个字符串来存储,会很浪费空间。所以实际在磁盘上存储数据的时候,一行数据里的NULL值肯定不会直接按照字符串的方式存放在磁盘上浪费空间。

    (2)NULL值是以二进制bit位来存储的
    对所有NULL值,不通过字符串在磁盘上存储,而是通过二进制的bit位来存储,一行数据里假设有多个字段的值都是NULL,那么这多个字段的NULL,就会以bit位的形式放在NULL值列表中
    假设一张表:
    CREATE TABLE customer(
    name VARCHAR(10) NOT NULL
    address VARCHAR(20)
    gender CHAR(1)
    job VARCHAR(30)
    school VARCHAR(50)
    )ROW_FORMAT=COMPACT
    假设客户表有5个字段,name,address,gender,job,school 其中4个变长字段,还有一个定长字段,然后第一个name字段声明了NOT NULL,就是不能为NULL,其他4个字段都可能为NULL,那么现在我们来假设这个表里有一条数据,
    磁盘上存储 “jack NULL m NULL xx_school” 这5个字段有两个字段都是NULL。

    (3)这行数据的磁盘存储格式
    磁盘上存储的格式如下:变长字段长度列表 NULL值列表 头信息 column1=value1 column2=value2… columnN=valueN
    先看下变长字段长度列表应该放什么东西,一共有4个变长字段,按照逆序顺序 school job address name 存放变长字段的值长度,说起来好需要区分一个问题,如果这个变长字段的值是NULL,就不用在变长字段 长度列表里存放他们的值长度了;
    所以第一次演进如下:0x09 0x04 NULL值列表 头信息 column1=value1 column2=value2… columnN=valueN
    接着来看下NULL值列表怎样存放?
    所有允许值为NULL的字段,只要允许为NULL就会占一个bit位,当然值允许为NULL,但不一定为NULL,如果bit位值为1说明是NULL,如果bit位职值为0说明不是NULL,比如 “jack NULL m NULL xx_school”,其中2个字段是NULL,2个字段不是NULL,
    所以4个bit位:1010,但是实际存放NULL值列表的时候,他是按逆序放的,所以在NULL值列表里放的是: 0101,
    另外实际NULL值存放的时候,不会说仅仅是4个bit位,一般起码是8个bit位的倍数,如果不足8个bit位就高位补0
    所以第二次演进如下:0x09 0x04 00000101 头信息 column1=value1 column2=value2… columnN=valueN

    (4)磁盘上一行数据如何读取?
    磁盘存储格式:0x09 0x04 00000101 头信息 column1=value1 column2=value2… columnN=valueN
    首先它必然把 变长字段长度列表 和 NULL值列表读取出来,通过综合分析一下,就知道有几个变长字段,那几个变长字段是NULL,因为NULL值列表里谁是NULL谁不是NULL都清楚。可以通过NULL值列表bit位为1的位置知道。
    此时可以从 变长字段长度列表中解析出来不为 NULL的变长字段的值长度,然后也知道哪几个字段是NULL,这样就能从实际的列值存储区域里,把每个字段的值取出来了。
    NULL值列表:存储的是数据表 列 中 字段为 null 的位置;

    在UTF-8编码下,一个英文字符是1个字节,”NULL”是四个字节 = 32位。字符串占用的空间是bit位存储占用的空间32倍。

    问题:这里二进制格式的NULL值列表,高位全是0,无法判断到底有多少个NULL值呀?
    解答
    允许为null的都会在这里,不足8个高位补0,超过8个允许为null的字段就会用2个字节的bit为,就是16个bit位,首先不为为null的null值列表用1表示。如果都是0表示不为null,我们不需要考虑,如果是1表示是空,我们会跳过这个位置。

    假设使用NULL字符串方式来保存,编码方式为UTF8,占用的位数=4(字符)3(UTF8中每个字符3个字节)8(每个字节8位)=96bit;而按照二进制的bit位来存储,只需要占用1bit,这就他们之间的差距