首页 > 数据库 >MySQL(九)InnoDB行格式

MySQL(九)InnoDB行格式

时间:2023-04-03 22:46:27浏览次数:46  
标签:00 存储 列表 InnoDB MySQL 格式 NULL row

InnoDB行格式

查看默认行格式:
select @@innodb_default_row_format;
查看数据库表使用的行格式
mysql> use atguigudb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> create table emp3 ( id int, name varchar(50) ) row_format=compact;
Query OK, 0 rows affected (0.02 sec)

mysql> show table status like 'emp3'\G
*************************** 1. row ***************************
           Name: emp3
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2023-04-03 00:27:36
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb3_general_ci
       Checksum: NULL
 Create_options: row_format=COMPACT
        Comment: 
1 row in set (0.00 sec)
修改行格式
mysql> alter table emp3 row_format=dynamic;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0


mysql> show table status like 'emp3'\G
*************************** 1. row ***************************
           Name: emp3
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2023-04-03 00:32:49
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb3_general_ci
       Checksum: NULL
 Create_options: row_format=DYNAMIC
        Comment: 
1 row in set (0.00 sec)

compact行格式

image-20230403153513530
  • 变长字段长度列表:mysql中支持变长的数据类型,即变长字段中存储的字节数不是固定的,如VARCHAR、VARBINARY、TEXT、BLOB类型,但是在实际存储真实数据的时候需要记录数据占用的字节数,COMPACT行格式将变长字段占用的长度放在记录的开头部位,形成变长字段长度列表

    字段的变长字段列表以及下面的存储都是倒序的,这是因为底层都是二进制,逆序正好是存放在低位

  • NULL值列表:Compact行格式会把表中可以为NULL的字段统一管理起来,存在这个标记为NULL值列表中,如果表中没有可以为NULL的字段,则NULL值列表也就不存在了

    image-20230403155339514

    如有三个字段a、b、c,其中a是主键,存储a=0,b=null,c=2,则行格式中的NULL值列表会存储01,0代表c不为null(倒序所以c在前面),0代表b为null,NULL值列表会自动跳过主键和NOT NULL字段

  • 记录头信息(5字节):前面讲了,见2.2

  • 记录的真实数据:一条记录的真实记录部分除了我们自己定义的列的数据,还会有三个隐藏列:

    image-20230403160414852
    • row_id:行id,唯一标识一条记录
    • transaction_id:事务id
    • roll_pointer:回滚指针

    row_id即是前面在介绍INNODB创建聚簇索引的时候,在没有主键和unique作为索引的情况下为每一列指定的一个自动主键

​ 下面创建一个表,来底层查看一下记录的二进制文件(开卷!)

image-20230403161439014

​ 然后查看数据库表的十六进制显示的ibd文件:

image-20230403161524445
  • 03 02 01:对应记录的变长字段长度列表,即倒序为col4、col2、col1的实际存储字节,col3为定长,所以不记录
  • 00:NULL值列表,表示全不为null
  • 00 00 10 00 2c(正好五个字节):记录头信息
  • 00 00 00 2b 68 00(6B):row_id
  • 00 00 00 00 06 05(6B):trasaction_id
  • 80 00 00 00 32 01 10(7B):roll_pointer
  • 61:16进制的a
  • 62 62: 16进制的bb
  • 62 62 20 ... 20:定长字段bb,20表示为空
image-20230403175245691
Dynamic与Compressed行格式
行溢出

​ 在创建表的时候,如使用varchar变长类型,按照类型大小应该能够设置varchar(65535),提示创建失败:[Err] 1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

CREATE TABLE test (
	`name` VARCHAR(65535)
)CHARSET=ASCII ROW_FORMAT=COMPACT;

使用ASCII编码的原因是一个字符占一个字节(变长类型的括号中的是字符),否则默认的表编码为utf8,则是65535个字符 = 65535 / 3 个字节

​ 而使用65532就能创建成功

CREATE TABLE test (
	`name` VARCHAR(65532)
)CHARSET=ASCII ROW_FORMAT=COMPACT;

原因就在于行格式中,由于记录变长,所以变长字段长度列表会占用两个字节,NULL值列表会占用1个字节

​ 如果使用NOT NULL约束,则就能创建65533大小的表:

CREATE TABLE test (
	`name` VARCHAR(65533) NOT NULL
)CHARSET=ASCII ROW_FORMAT=COMPACT;

行溢出:一个页的大小为16KB,即16384个字节,而上面一个字段就用去65535,这种一个页存放不下一条记录的现象,叫做行溢出

页的扩展:在Compact和Redundant行格式中,当出现占用空间特别大的列导致行溢出的时候,在记录真实的数据出只会存储一部分数据,而把剩余数据分散存储在其他几个页中进行分页存储,并使用20个字节存储指向这些地址(并且包含这些分散在其他页的数据所占的字节数),从而可以找到剩余数据所在的页。

image-20230403182347343
Dynamic与Compressed行格式

在MySQL8.0中,默认的行格式就是Dynamic,Dynamic、Compressed行格式和Compact行格式基本相同,只不过在处理行溢出上有所差异,采用的是完全的行溢出方式即行溢出的字段完全不存放真实的数据,只存放20字节存储溢出页的地址。

image-20230403183153169

​ 而Compressed行格式则是在Dynamic的基础上对存储在行之中的数据使用zlib算法进行了压缩,因此对于BLOB、TEXT、VARCHAR这种大长度类型的数据进行有效的存储。

Redundant行格式

​ Redundant行格式是MySQL5.0之前InnoDB的行记录存储方式,和Compact的主要区别在于使用了字段长度偏移列表,而没有变长字段长度列表NULL值列表

image-20230403184416951

字段长度偏移列表:与变长长度列表主要有两处不同:

  • Redundant行格式会将该条记录的所有列(包含隐藏列)的长度按照逆序存储到字段长度偏移列表(记录了全部长度,自然也就不需要NULL值列表了)
  • 使用的是相邻两个数值的差值来计算每个列值的长度

​ 除此之外还有头记录信息中的两个不同,这里就不写了 - -

标签:00,存储,列表,InnoDB,MySQL,格式,NULL,row
From: https://www.cnblogs.com/tod4/p/17284767.html

相关文章

  • MySQL(九)InnoDB数据结构
    InnoDB数据结构1数据库的存储结构:页​ 索引信息和数据记录都是保存在文件上的,确切来说是保存在页结构中;另一方面,索引是在存储引擎上实现的,MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同的存储引擎的存放格式是不同的,比如Memory甚至不使用磁盘进行存储数据。......
  • MySQL(十)表空间结构:区、段与碎片区
    表空间结构:区、段与碎片区为什么要有区?​ B+树中的每一层的页都会形成一个双向链表,双向链表之间的物理位置可能会离得非常远,当遇到范围查询的适用场景的时候,就会定位到最左边和最右边的记录,然后沿着双向链表一直扫描,而如果这其中的两个页面物理上离得特别远,就会成为随机I/O,由于......
  • MYSQL基础知识之DDL语句
    一、DDL概念DDL(DataDefinitionLanguage)语言:数据定义语言,用来定义数据库对象,如数据库、数据表和数据字段,主要是进行定义/改变表的结构、数据类型、表之间的链接等操作。常用的语句关键字有CREATE、DROP、ALTER等。 二、数据库操作2.1、linux环境连接数据库语法:mysql-u用......
  • Mysql主从复制
    工作原理图:主从复制的原理:分为同步复制和异步复制,实际复制架构中大部分为异步复制。复制的基本过程如下:1).Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;2).Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请......
  • mysql数据库优化大全
    数据库优化sql语句优化索引优化加缓存读写分离分区分布式数据库(垂直切分)水平切分MyISAM和InnoDB的区别:1.InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;2......
  • MySQL实战45讲 笔记
    笔记不要小看一条update语句,在生产机上使用不当可能会导致业务停滞,甚至崩溃。当我们要执行update语句的时候,确保where条件中带上了索引列,并且在测试机确认该语句是否走的是索引扫描,防止因为扫描全表,而对表中的所有记录加上锁。我们可以打开MySQL里的sql_safe_updates参数......
  • MySQL索引详细介绍
    一、什么是索引?为什么要建立索引?索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很......
  • mysql多实例配置
    实现在一台服务器上开两个数据库服务。配置:[mysqld_multi]user=rootmysqld=/usr/local/mysql/bin/mysqld_safemysqladmin=/usr/local/mysql/bin/mysqladmin[mysqld1]datadir=/dir1port=3307pid-file=/dir1/mysqld1.pidlog-error=/dir1/mysqld1.errsocket=/dir1/mysqld1.sock[mysqld......
  • 高可靠myql配置-双MysqlRouter+MHA
    普通的主备方案 双MysqlRouter+MHA  3.1资源角色 主机IP 软件版本 备注RouterMaster 192.10.13.203 8.0.16 192.10.13.205RouterSlave 192.10.13.204 8.0.16 192.10.13.205MHAManager 192.10.13.206 MHA0.56 MHANode&Mysql主 192.10.13.201 MHA0.56&My......
  • ansible 部署mysql 5.7
    准备工作创建roles目录#mkdir-pv/data/apps/ansible/roles/mysql-5.7/{files,tasks,handlers,templates,vars}hosts[ubuntu]172.16.18.31ansible_ssh_port=22ansible_ssh_user=ubuntuhostname=app-01测试连通性#ansibleubuntu-mping172.16.18.247|SUCCESS=......