Mysql compact行格式

InnoDB行格式类型(Compact格式)

Compact行格式示意图:

Mysql中变长字段是如何存储的

mysql支持变长的数据类型,varchar(m)、varbinary(m)、text、blob类型等,这些变长的数据类型占用的存储空间分为两部分:

   1.真正的数据内容

   2.申明占用的字节数

如果不保存真实数据占用字节数,那么mysql服务器无法判断出真实数据有多长,导致无法准确取数据 。所以我们在存储真实数据的时候需要顺便把这些数据占用的字节数也存起来。

在compact行格式中,把所有边长类型的长度存放在行记录的开头部位形成一个列表,按照列的逆序存放

CHAR是一种固定长度的类型,VARCHAR则是一种可变长度的类型VARCHAR(M),M代表最大能存多少个字符。( MySQL5.0.3以前是字节,以后就是字符)

基本存储方式

变长字段的长度列表,null值列表,数据头,column01的值,column02的值,column0n的值...
  •  

变长字段如何存储

  • 某行中有一个变长字段
    # 假如有三个字段 id,name,age其中name是变长类型(Varchar)
    |id|name|age|
    |1|wang|18|
    
    磁盘里的存储为:
    0x04 null值列表 数据头 1 wang 18
    
    # 其中0x04表示name长度为4
  • 多行的数据也是紧挨着存储
    # 假如有三个字段 id,name,age其中name是变长类型(Varchar)
    |id|name|age|
    |1|wang|18|
    |2|li|20|
    
    磁盘里的存储为:
    0x04 null值列表 数据头 1 wang 18 0x02 null值列表 数据头 2 li 20
  • 单行中多个变长字段如何存储
    # 假如有三个字段 id,name,desc,age其中name,desc是变长类型(Varchar)
    |id|name|desc|age|
    |1|wang|shuaige|18|
    
    磁盘里的存储为:
    0x07 0x04 null值列表 数据头 1 wang shuaige 18
    
    # 其中0x04表示name长度为4,0x07表示desc的长度为7

NULL值列表是如何存储的

Compact行格式会把可以为NULL的列统一管理起来,存一个标记为在NULL值列表中,如果表中没有允许存储NULL 的列,则 NULL值列表也不存在了。
二进制位的值为1时,代表该列的值为NULL。
二进制位的值为0时,代表该列的值不为NULL。

    # 假如有三个字段 id,name,age其中name是变长类型(Varchar)
    |id|name|age|
    |1|wang|18|
    
    磁盘里的存储为:
    0x04 00 数据头 1 wang 18
    
    # 其中00表示name,age都不为空,当然这里id是主键,肯定不为空,所以没记录

记录头信息

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

记录的真实数据

记录的真实数据除了我们自己定义的列的数据以外,还会有三个隐藏列:
在这里插入图片描述
实际上这几个列的真正名称其实是:DB_ROW_ID、DB_TRX_ID,DB_ROLL_PTR。

一个表没有手动定义主键,则会选取一个Unique键作为主键,如果连Unique键都没有定义的话,则会为表默认添加一个名为row_id的隐藏列作为主键。所以row_id是在没有自定义主键以及Unique键的情况下才会存在的。

行溢出数据

VARCHAR(M)类型的列最多可以占用65535个字节。其中的M代表该类型最多存储的字符数量,如果我们使用ascii字符集的话,一个字符就代表一个字节,我们看看VARCHAR(65535)是否可用:
在这里插入图片描述
报错信息表达的意思是:MySQL对一条记录占用的最大存储空间是有限制的,除BLOB或者TEXT类型的列之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字节。这个65535个字节除了列本身的数据之外,还包括一些其他的数据,比如说我们为了存储一个VARCHAR(M)类型的列,其实需要占用3部分存储空间:

  1. 真实数据
  2. 变长字段真实数据的长度
  3. NULL值标识

如果该VARCHAR类型的列没有NOT NULL属性,那最多只能存储65532个字节的数据,因为变长字段的长度占用2个字节,NULL值标识需要占用1个字节。
在这里插入图片描述
在这里插入图片描述

记录中的数据太多产生的溢出

一个页的大小一般是16KB,也就是16384字节,而一个VARCHAR(M)类型的列就最多可以存储65533个字节,这样就可能出现一个页存放不了一条记录。

CompactReduntant行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分数据,把剩余的数据分散存储在几个其他的页中,然后记录的真实数据处用20个字节存储指向这些页的地址(当然这20个字节中还包括这些分散t在其他页面中的数据的占用的字节数),从而可以找到剩余数据所在的

记录中的数据太多产生的溢出

一个页的大小一般是16KB,也就是16384字节,而一个VARCHAR(M)类型的列就最多可以存储65533个字节,这样就可能出现一个页存放不了一条记录。

CompactReduntant行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分数据,把剩余的数据分散存储在几个其他的页中,然后记录的真实数据处用20个字节存储指向这些页的地址(当然这20个字节中还包括这些分散t在其他页面中的数据的占用的字节数),从而可以找到剩余数据所在的

Dynamic和Compressed格式

这两种行格式类似于COMPACT行格式,只不过在处理行溢出数据时有点儿分歧,它们不会在记录的真实数据处存储一部分数据,而是把所有的数据都存储到其他页面中,只在记录的真实数据处存储其他页面的地址。另外,Compressed行格式会采用压缩算法对页面进行压缩。

参考资料:
Mysql中变长字段是如何存储的     https://blog.csdn.net/weixin_29491885/article/details/104846592

innodb行格式和数据页以及索引底层原理分析  https://blog.csdn.net/java_eehehe/article/details/105529353          https://www.cnblogs.com/qcfeng/p/7325307.html

猜你喜欢

转载自blog.csdn.net/liuming690452074/article/details/113820877
今日推荐