[转帖]MySQL提升笔记(4)InnoDB存储结构

mysql,提升,笔记,innodb,存储,结构 · 浏览次数 : 0

小编点评

**Compact 行记录格式** **行记录格式:** * 首部: * 非「NULL」变长字段长度列表,按照列的顺序逆序排列,长度不超过 2 字节。 * «NULL」标志位,指示该行数据中是否有「NULL」值,有则用 1 表示。 * 记录头信息(「record」 「header」)。 * 记录头信息(「record」 「header」): * 用户定义的列大小。 * 2 个隐藏列:事务 1「D」 列和回滚指针列。 * 6 字节的 「rowid」 列(仅在 InnoDB 中定义主键时)。 * 数据部分: * 每行数据除了用户定义的列外,还有两个隐藏列。 * 每行数据除了用户定义的列外,还有两个隐藏列。 * 文件尾部: * 文件结构信息,包含校验和、数据页大小等信息。 * 可选的索引信息。 **数据页结构:** * 7 个主要部分组成: * **File**:文件头、页头、文件尾部。 * **Header**:记录头信息。 * **Page**:数据页,存放实际数据。 * **Index**:数据页索引。 * **User**:用户记录。 * **Records**:数据记录。 * **Free**:空闲空间。 * **Page Directory**:页目录,存储索引信息。

正文

https://cdn.modb.pro/u/310923

 

这一节本来计划开始索引的学习,但是在InnoDB存储引擎的索引里,存在一些数据存储结构的概念,这一节先了解一下InnodDB的逻辑存储结构,为索引的学习打好基础。

从InnoDB存储引擎的存储结构看,所有数据都被逻辑地放在一个空间中,称之为表空间(tablespace)、区(extent)、页(page)组成,页在一些文档中也被称之为块(block)。

1、InnoDB逻辑存储结构

InnoDB存储引擎的逻辑存储结构大致如图:

InnoDB逻辑存储结构

这张图更清晰地展示了这些空间的包含关系:

innodb_tablespace

1.1、表空间(Tablespace)

表空间可以看做InnoDB逻辑结构的最高层,所有的数据都放在表空间中。

在默认情况下,InnoDB存储引擎都有一个共享表空间ibdata1,即所有数据都存放在这个表空间内。如果用户启用了参数innodb_file_per_table
,则每张表内的数据可以单独放到一个表空间内。

如果启用了innodb_file_per_table
参数,也需要注意,每张表的表空间存放的只是数据、索引和插入缓冲Bitmap页,其它类的数据,如回滚(undo)信息,插入缓冲索引页、系统事务信息,二次写缓冲等还是存放在原来的共享表空间内。

1.2、段(Segment)

表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。

InnoDB存储引擎表是索引组织(index organized
)的,因此数据即索引,索引即数据。那么数据段即为B+树的叶子节点(Leaf node segment),索引段即为B+树的非索引节点(Non-leaf node segment),这些内容在后面的索引学习里会详细介绍。

1.3、区(extend)

区是由连续页组成的空间,在任何情况下每个区的大小都为1MB。为了保证区中页的连续性,InonoDB存储引擎一次从磁盘申请4-5个区。在默认情况下,InnoDB存储引擎的页的大小为16KB,即一个区中应有64个连续的页。

InnoDB1.0.x版本开始引入压缩页,每个页的大小可以通过参数KEY_BLOCK_SIZE设置为2K、4K、8K,因此每个区对应的页尾512、256、128.

InnoDB1.2.x版本新增了参数innodb_page_size,通过该参数可以将默认页的大小设置为4K、8K,但是页中的数据不是压缩的。

但是有时候为了节约磁盘容量的开销,创建表默认大小是96KB,区中是64个连续的页。(对于一些小表)

1.4、页(page)

页是InnoDB存储引擎磁盘管理的最小单位,每个页默认16KB;InnoDB存储引擎从1.2.x版本开始,可以通过参数innodb_page_size将页的大小设置为4K、8K、16K。

若设置完成,则所有表中页的大小都为innodb_page_size,不可以再次对其进行修改,除非通过mysqldump导入和导出操作来产生新的库。

innoDB存储引擎中,常见的页类型有:

✅  数据页(B-tree Node)

✅ undo页(undo Log Page)

✅ 系统页 (System Page)

✅ 事务数据页 (Transaction System Page)

✅ 插入缓冲位图页(Insert Buffer Bitmap)

✅ 插入缓冲空闲列表页(Insert Buffer Free List)

✅ 未压缩的二进制大对象页(Uncompressed BLOB Page)

✅ 压缩的二进制大对象页 (compressed BLOB Page)

1.5、行(row)

InnoDB存储引擎是面向行的(row-oriented),也就是说数据是按行进行存放的,每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2-200,即7992行记录。

「2、InnoDB」 行记录格式

「InnoDB」 存储引擎和大多数数据库一样(如 「Oracle」 和 「Microsoft」 「SQL」 「Server」 数据库),记录是以行的形式存储的。这意味着页中保存着表中一行行的数据。在 「InnoDB」 1.0x 版本之前,「InnoDB」 存储引擎提供了 「Compact」 和 「Redundant」 两种格式来存放行记录数据,这也是目前使用最多的一种格式。

2.1、Compact 行记录格式

「Compact」 行记录是在 「MySQL」 5.0 中引人的,其设计目标是髙效地存储数据。简单来说,一个页中存放的行数据越多,其性能就越髙。

下图显示了 「Compact」 行记录的存储方式:

**Compact** 行记录

「Compact」 行记录格式的首部是一个非 「NULL」 变长字段长度列表,并且其是按照列的顺序逆序放置的,其长度为:

  • 若列的长度小于 255 字节,用 1 字节表示;

  • 若大于 255 个字节,用2 字节表示。

变长字段的长度最大不可以超过 2 字节,这是因在 「MySQL」 数据库中 「VARCHAR」 类型的最大长度限制为 65535。变长字段之后的第二个部分是 「NULL」 标志位,该位指示了该行数据中是否有 「NULL」 值,有则用 1 表示。

接下来的部分是记录头信息(「record」 「header」),固定占用5 字节(40 位)。每位含义见表:

名称大小(bit)描述
() 1 未知
() 1 未知
deleted_flag 1 该行是否已被删除
min_rec_flag 1 如果该行记录是预定义为最小的记录,为1
n_owned 4 该记录拥有的记录数,用于Slot
heap_no 13 索引堆中该条记录的索引号
record_type 3 记录类型,000(普通),001(B+Tree节点指针),010(Infimum),011(Supremum)
next_record 16 页中下一条记录的相对位置
Total 40(5Byte) nothing

最后的部分就是实际存储每个列的数据。

需要特别注意的是,「NULL」 不占该部分任何空间,即 「NULL」 除了占有 「NULL」 标志位,实际存储不占有任何空间。另外有一点需要注意的是,每行数据除了用户定义的列外,还有两个隐藏列,事务 1「D」 列和回滚指针列,分别为 6 字节和 7 字节的大小。若 「InnoDB」 表没有定义主键,每行还会增加一个 6 字节的 「rowid」 列。

「Redundant」 是 「MySQL」 5 . 0 版本之前 「InnoDB」 的 行 记 录 存 储 方 式,这里就不展开。

2.2、行溢出数据

「InnoDB」 存储引擎可以将一条记录中的某些数据存储在真正的数据页之外。因为一般数据页默认大小为16KB,假如一个数据页存储不了插入的数据,这时肯定就会发生行溢出。

行数据溢出

一般认为 「BLOB」「LOB」 这类的大对象列类型的存储会把数据存放在数据页之外。但是,「BLOB」 也可以不将数据放在溢出页面,而且即便是 「VARCHAR」 列数据类型,依然有可能被存放为行溢出数据。

3、「InnoDB」 数据页结构

页是 「InnoDB」 存储引擎管理数据库最小磁盘单位。页类型为 B-tree Node 的页存放的即是表中行的实际数据了。

「InnoDB」 数据页由以下 7 个部分组成:

  • 「File」 「Header」 (文件头)

  • 「Page」 「Header」 (页头)

  • 「Infimun」 和 「Supremum」 「Records」

  • 「User」 「Records」 (用户记录,即行记录)

  • 「Free」 「Space」 (空闲空间)

  • 「Page Directory」 (页目录)

  • 「File」 「Trailer」 (文件结尾信息)

**InnoDB** 存储引擎数据页结构

其中 「File」 「Header」「Page」 「Header」「File」 「Trailer」的大小是固定的, 分别为 38、56、8 字节,这些空间用来标记该页的一些信息,如 「Checksum」, 数据页所在 「B」+ 树索引的层数等。「User」 「Records」「Free」 「Space」「Page」 「Directory」 这些部分为实际的行记录存储空间,因此大小是动态的。




参考:

 

【1】:《MySQL技术内幕 InnoDB存储引擎》

【2】:[MySQL Architecture and Components](https://lalitvc.wordpress.com/2016/11/03/mysql-architecture-and-components/)

【3】:[了解 MySQL的数据行、行溢出机制吗?](https://www.cnblogs.com/zhuchangwu/p/14035330.html)

【4】:[InnoDB数据页结构分析](https://www.jianshu.com/p/9372c8e4a169)

【5】:[InnoDB数据页结构 ](https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483678&idx=1&sn=913780d42e7a81fd3f9b747da4fba8ec&chksm=979688eca0e101fa0913c3d2e6107dfa3a6c151a075c8d68ab3f44c7c364d9510f9e1179d94d&mpshare=1&scene=1&srcid=06240BXzIzzl2NMsxdtDNhOd&sharer_sharetime)
【6】:[InnoDB -- 行记录格式 ](http://zhongmingmao.me/2017/05/07/innodb-table-row-format/)

与[转帖]MySQL提升笔记(4)InnoDB存储结构相似的内容:

[转帖]MySQL提升笔记(4)InnoDB存储结构

https://cdn.modb.pro/u/310923 这一节本来计划开始索引的学习,但是在InnoDB存储引擎的索引里,存在一些数据存储结构的概念,这一节先了解一下InnodDB的逻辑存储结构,为索引的学习打好基础。 从InnoDB存储引擎的存储结构看,所有数据都被逻辑地放在一个空间中,称之为

[转帖]在 TiDB 中正确使用索引,性能提升 666 倍

https://tidb.net/book/tidb-monthly/2022/2022-04/usercase/index-666 背景​ 最近在给一个物流系统做TiDB POC测试,这个系统是基于MySQL开发的,本次投入测试的业务数据大概10个库约900张表,最大单表6千多万行。 这个规模不算

[转帖]MySQL 慢查询日志深入理解

https://www.jb51.net/article/210312.htm + 目录 什么是慢查询日志 MySQL的慢查询日志是 MySQL提供的一种日志记录,它用来记录在 MySQL 中响应时间超过阀值的语句,具体指运行时间超过long_query_time 值的 SQL,则会被记录到慢查询日

[转帖]MySQL事务的开启与提交,autocommit自动提交功能

MySQL事务的开启与提交,autocommit自动提交功能 https://www.cnblogs.com/deverz/p/6547866.html 对于一个MySQL数据库(InnoDB),事务的开启与提交模式无非下面这两种情况:1、若参数autocommit=0,事务则在用户本次对数据进行操

[转帖]Mysql向表中循环插入数据

如何查看MySQL的当前存储引擎 看你的mysql现在已提供什么存储引擎: mysql> show engines; 看你的mysql当前默认的存储引擎: mysql> show variables like '%storage_engine%'; 创建表 create table per2 (id

【转帖】Mysql一张表可以存储多少数据

https://www.cnblogs.com/wenbochang/p/16723537.html Mysql一张表可以存储多少数据 在操作系统中,我们知道为了跟磁盘交互,内存也是分页的,一页大小4KB。同样的在MySQL中为了提高吞吐率,数据也是分页的,不过MySQL的数据页大小是16KB。(确

【转帖】MySQL 8.0 hash join有重大缺陷?

我并不这么看。 友情提醒:本文建议在PC端阅读。 徐春阳老师发文爆MySQL 8.0 hash join有重大缺陷。 文章核心观点如下:多表(比如3个个表)join时,只会简单的把表数据量小的放在前面作为驱动表,大表放在最后面,从而导致可能产生极大结果集的笛卡尔积,甚至耗尽CPU和磁盘空间。 就此现

[转帖]MySQL InnoDB存储引擎大观

https://baijiahao.baidu.com/s?id=1709263187856706948&wfr=spider&for=pc MySQL InnoDB 引擎现在广为使用,它提供了事务,行锁,日志等一系列特性,本文分析下 InnoDB的内部实现机制,MySQL 版本为 5.7.24,操

【转帖】《MySQL高级篇》四、索引的存储结构

1. 为什么使用索引 假如给数据使用 二叉树 这样的数据结构进行存储,如下图所示 2、索引及其优缺点 2.1 索引概述 2.2 优点 类似大学图书馆建书目索引,提高数据检索的效率,降低 数据库的 IO 成本 这也是创建索引的主要的原因。通过创建唯一索引,可以保证数据库表中每一行 数据的唯一性 (唯一

[转帖]深入理解mysql-第十二章 mysql查询优化-Explain 详解(下)

我们前面两章详解了Explain的各个属性,我们看到的都是mysql已经生成的执行计划,那这个执行计划的是如何生成的?我们能看到一些过程指标数据吗?实际mysql贴心为我们提供了执行计划的各项成本评估指标的以及优化器生成执行计划的整个过程的方法。 一、查看执行计划计算的成本数据 我们上边介绍的EXP