MySQL高级第四篇:InnoDB存储结构之页、区、段和表空间
- 一、数据库的存储结构:页
- 1. 页是磁盘与内存交互的基本单位
- 2. 页的结构
- 3. 页的上层结构
- 二、页的内部结构
- 三、InnoDB行格式
- 1. Compact行格式
- 2. Dynamic 和 Compressed 行格式
- 四、区、段、碎片区和表空间
- 1. 为什么要有区?
- 2.为什么会有段?
- 3. 为什么会有碎片区?
- 4. 表空间
一、数据库的存储结构:页
我们都知道,索引信息以及数据记录都是保存在文件上的,确切说是存储在页结构中,并且索引是在存储引擎中实现的,存储引擎负责对表中数据的读取和写入工作。
1. 页是磁盘与内存交互的基本单位
- InnoDB将
数据划分为若干个页
,页的大小默认为16KB。 - 以页作为
磁盘和内存之间交互的基本单位
,也就是一次最少从磁盘中读取16KB的内容到内存中,也就是说,在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载。
2. 页的结构
- 多个页不在物理结构上相连,而是通过双向链表连接。
- 每个页中存储多条记录,按照主键从小到大顺序以单向链表连接。
3. 页的上层结构
- 页的上层结构是区,一个区包含64个连续的页,大小刚好为 1MB
- 区的上级结构是段,段是数据库的分配单位
- 段的上级结构是表空间,它是一个逻辑容器,表空间存储一个或多个段,数据库由一个或多个表空间组成。
二、页的内部结构
- 数据页的16KB大小的存储空间被划分为七个部分,分别是 文件头(File Header)、页头(Page Header)、最大最小记录(Infimum+supremum)、用户记录(User Records)、空闲空间(Free Space)、页目录(Page Directory)和文件尾(File Tailer)。
三、InnoDB行格式
- 我们平时的数据以行为单位来向表中插入数据,这些记录在磁盘上的存放方式被称为
行格式或者记录格式
。 - InnoDB存储引擎设计了4种不同类型的行格式,分别是 Compact、Redundant、Dynamic 和 Compressed。
- MySQL8.0 5.7默认行格式为 Dynamic。
1. Compact行格式
- MySQL5.1中,默认Compact行格式
2. Dynamic 和 Compressed 行格式
- 在 Compact 和 Reduntant 行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分数据,把剩余的数据分散存储在几个其他的页中进行分页存储,然后记录的真实数据处用20个字节存储指向这些页的地址,从而可以找到剩余数据所在的页。
四、区、段、碎片区和表空间
1. 为什么要有区?
- B+树的每一层中的页都会形成一个双向链表,如果是以页为单位来分配存储空间的话,双向链表相邻的两个页
之间的物理位置可能离得非常远。 - 如果链表中相邻的两个页物理位置离得非常远,就是所谓的随机I/0,非常慢。
- 我们应该
尽量让链表中相邻的页的物理位置也相邻,也就是所谓的顺序I/0,提高速度
。 - 一个区就是在物理位置上连续的64个页,在表中数据量大的时候,为某个索引分配空间的时候就不再按照页为单位分配了,而是
按照区为单位分配
,虽然这样会浪费一点空间,但可以消除很多的随机/O,功大于过。
2.为什么会有段?
- 对于范围查询,其实是对B+树叶子节点中的记录进行顺序扫描,而如果不区分叶子节点和非叶子节点,统统把节点代表的页面放到申请到的区中的话,进行范围扫描的效果就大打折扣了。
- 所以InnoDB对B+树的叶子节点和非叶子节点进行了区别对待,叶子节点有自己独有的区,非叶子节点也有自己独有的区。
-
存放叶子节点的区的集合和存放非叶子节点的区的集合各自是一个段
。 - 数据段即为B+树的叶子节点,索引段即为B+树的非叶子节点。
- 段不对应表空间中某一个连续的物理区域,而是一个逻辑上的概念,由若干个零散的页面以及一些完整的区组成。
3. 为什么会有碎片区?
- 默认情况下,一个使用InnoDB存储引擎的表只有一个聚簇索引,一个索引会生成2个段,而段是以区为单位申请存储空间的,一个区默认占用1M,所以默认情况下一个只存了几条记录的小表也分配2M的存储空间,以后每次添加一个索引都要多申请2M的存储空间,这是极大的浪费。
- 为了考虑
以完整的区为单位分配给某个段对于数据量较小的表太浪费存储空间
的这种情况,InnoDB提出了一个碎片(fragment)区的概念。在一个碎片区中,并不是所有的页都是为了存储同一个段的数据而存在的,而是碎片区中的页可以用于不同的目的,比如有些页用于段A,有些页用于段B,有些页甚至哪个段都不属于。 -
碎片区直属于表空间,并不属于任何一个段
。 - 所以此后为某个段分配存储空间的策略是:
- 在刚开始向表中插入数据的时候,段是从某个碎片区以单个页面为单位来分配存储空间的。
- 当某个段已经占用了32个碎片区页面之后,就会申请以完整的区为单位来分配存储空间。
4. 表空间
- 表空间可以看做是InnoDB存储引擎逻辑结构的最高层,
所有的数据都存放在表空间中
。 - 表空间是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以有一个或多个段。
- 表空间从管理上可以分为系统表空间、独立表空间、撤销表空间和临时表空间等。