4_InnoDB的记录结构

MySQL服务器中存储引擎负责对表中数据的读取和写入

为支持不同的特性,MySQL提供了不同类型的存储引擎,其中存放数据的格式各不相同

专注于最常用的InnoDB存储引擎。


InnoDB页简介

InnoDB将表中的数据存储到磁盘(断电不丢失),处理数据发生在内存

读取需要把磁盘中的数据加载到内存中,写入/修改需要把内存中的内容刷新到磁盘上。

磁盘读写的速度比内存读写慢了几个数量级,一次操作通常涉及多条记录,若磁盘与内存交互时每条记录都需要访问磁盘,则会执行太慢。

InnoDB中以作为磁盘和内存之间交互的基本单位,页的大小一般为16KB


InnoDB行格式

记录在磁盘上的存放方式也被称为行格式

InnoDB存储引擎有4种不同类型的行格式。

  • Compact
  • Redundant;
  • Dynamic;
    1. 默认行格式
    2. 行溢出时,只记录存储其他页面的地址,所有的字节都会存储到其他页面中;
  • Compressed;
    1. 采用压缩算法对页面进行压缩;

指定行格式

  • CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
  • ALTER TABLE 表名 ROW_FORMAT=行格式名称

Compact

Compact行格式
  1. 记录的额外信息

    1. 变长字段长度列表

      1. 可以存储不固定字节数的的列称为变长字段
        1. 变长类型VARCHAR(M)、VARBINARY(M)、TEXT、BLOB;
        2. 定长类型 + 变长字符集(GBK、UTF8等);
      2. 存储数据占用的字节数
      3. 各变长字段长度数按照列的顺序逆序存放,形成变长字段长度列表;
      4. 细节
        1. 如果该可变字段允许存储的最大字节数(M×W)超过255字节并且真实存储的字节数(L)超过127字节,则使用2个字节,否则使用1个字节,其中M为字符集的Maxlen,W为字符数;
        2. 变长字段长度列表中只存储值为非NULL的列内容占用的长度,不存储值为NULL的列的长度;
        3. 非变长的数据类型列不需要存储列长;
    2. NULL值列表

      1. 列存储NULL值,为节省空间,不会存储真实数据NULL值,而是在额外信息的NULL值列表统一标识;
      2. 处理过程
        1. 统计表中允许存储NULL的列;
          1. 主键列、被NOT NULL修饰的列不可以存储NULL值;
          2. 默认列可以存储NULL值;
          3. 若不存在允许存储 NULL 的列,则NULL值列表也不存在;
        2. 将每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列
          1. 二进制位为0,代表列的值不为NULL;
          2. 二进制位为1,代表列的值为NULL;
          3. 二进制位用整数个字节表示,不满足则在字节的高位补0;
    3. 记录头信息

      1. 由固定的40个二进制位(5个字节)组成。

      2. 记录头信息
      3. 名称 大小(单位:bit) 描述
        预留位1 1 没有使用
        预留位2 1 没有使用
        delete_mask 1 标记该记录是否被删除
        min_rec_mask 1 B+树的每层非叶子节点中的最小记录都会添加该标记
        n_owned 4 表示当前记录拥有的记录数
        heap_no 13 表示当前记录在记录堆的位置信息
        record_type 3 表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录
        next_record 16 表示下一条记录的相对位置
  2. 记录的真实数据

    1. 隐藏列

      1. 简写列名 真正名称 是否必须 占用空间 描述
        row_id DB_ROW_ID 6字节 行ID,唯一标识一条记录
        transaction_id DB_TRX_ID 6字节 事务ID
        roll_pointer DB_ROLL_PTR 7字节 回滚指针
      2. InnoDB主键的生成策略:用户自定义主键 > Unique键 > row_id

      3. 在没有自定义主键以及Unique键时,才会添加row_id

    2. 用户数据

      1. 定长字段,填充0值;
      2. 变长字段,不存储;

行溢出数据

VARCHAR最大字符数

BLOB或者TEXT类型的列之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字节

  1. 用户数据;
  2. 变长字段长度列表;
  3. NULL值列表;

计算VARCHAR(M)最大字符数

  1. 变长字段长度占2个字节;
  2. NULL标识需要1个字节,NOT NULL则无需占用;
  3. ASCII字符集中1个字符占1个字节;
  4. 最大字符数为(65535 - 2 - 0) / 1 = 65533;
  5. 若为utf8字符集,则最大字符数为(65535 - 2 - 0) / 3 = 21844;

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

  1. 一页大小为16384B < VARCHAR(M)类型的最大占用存储65532B,存在一页无法存放一条记录的情况;
  2. 行溢出
    1. 在本记录的真实数据处只会存储该列的前768个字节的数据指向其他页的地址
    2. 把存储超出768字节的数据存放到其他页中,这些页面也被称为溢出页
    3. 行溢出
  3. 行溢出的临界点
    1. 当单行单列,一页2条数据时,数据字节数n > 8098;
    2. 如果在一个行中存储了很大的数据,可能会发生行溢出,注意宽表

posted @ 2024-10-06 12:38  夜是故乡明  阅读(2)  评论(0编辑  收藏  举报