一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人。如有侵权,请留言,我及时删除!
一、MySQL数据存储结构解析
1、mysql数据存储结构的组成
从 InnoDB 逻辑存储结构来看,所有的数据都被逻辑的存放在一个空间中,这个空间就叫做表空间(tablespace)而每一个独立表空间都会有一个.ibd数据文件。表空间由 段(segment)、区(extent)、页(page)组成。
表空间tablespace(一个ibd数据文件)–>Segment(段)–>Extent(区–>Page(页–>Row(行)
2、mysql对应的数据文件
当我们创建一个表之后,在磁盘上会有对应的表名称.ibd
的磁盘文件。表空间的磁盘文件里面有很多的数据页,一个数据页最多16kb,因为不可能一个数据页一个磁盘文件,所以数据区的概念引入了
一个数据区对应64个数据页,就是16kb,一个数据区是1mb,256个数据区被划分为一组,对于表空间而言,他的第一组数据区的第一个数据区的前3个数据页,都是固定的,里面存放了一些描述性的数据。比 如FSP_HDR这个数据页,他里面就存放了表空间和这一组数据区的一些属性。IBUF_BITMAP 数据页,存放的就是insert buffer的信息,INODE 数据页存放的也是特殊信息。
再次强调一遍:我们平时创建的那些表都是有对 应的表空间的,每个表空间就是对应了磁盘上的数据文件,在表空间里有很多组数据区,一组数据区是256个数据区, 每个数据区包含了64个数据页,是1mb
3、mysql数据存储结构的大小
4、表空间(tablespace)详解
InnoDB存储引擎将InnoDB表保存在一个表空间内,该表空间可由数个文件创建。这样,表的大小就能超过单独文件的最大容量。表空间可包括原始磁盘分区,从而使得很大的表成为可能。表空间的最大容量为64TB。
表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中
。
表空间是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以有一个或多个段。
表空间从管理上可以分为系统表空间、独立表空间、撤销表空间和临时表空间等。
5、数据段(segment)详解
段(segment)
段(Segment)分为索引段,数据段,回滚段等。其中索引段就是非叶子结点部分,而数据段就是叶子结点部分,回滚段用于数据的回滚和多版本控制。一个段包含256个区(256M大小)。
一个段包含多少区:256个区
对于范围查询,其实是对B+树叶子节点中的记录进行顺序扫描,而如果不区分叶子节点和非叶子节点,统统把节点代表的页面放到申请到的区中的话,进行范围扫描的效果就大打折扣了。
所以InnoDB对B+树的叶子节点和非叶子节点进行了区别对待,叶子节点有自己独有的区,非叶子节点也有自己独有的区。存放叶子节点的区的集合和存放非叶子节点的区的集合各自是一个段。
数据段即为B+树的叶子节点,索引段即为B+树的非叶子节点。段不对应表空间中某一个连续的物理区域,而是一个逻辑上的概念,由若干个零散的页面以及一些完整的区组成。
6、区(extent)详解
区是页的集合,一个区包含64个连续的页,默认大小为 1MB (64*16K)。
B+树的每一层中的页都会形成一个双向链表,如果是以页为单位来分配存储空间的话,双向链表相邻的两个页之间的物理位置可能离得非常远。如果链表中相邻的两个页物理位置离得非常远,就是所谓的随机I/0,非常慢。我们应该尽量让链表中相邻的页的物理位置也相邻,也就是所谓的顺序I/0,提高速度。一个区就是在物理位置上连续的64个页,在表中数据量大的时候,为某个索引分配空间的时候就不再按照页为单位分配了,而是按照区为单位分配,虽然这样会浪费一点空间,但可以消除很多的随机/O。
碎片(fragment)区的概念
默认情况下,一个使用InnoDB存储引擎的表只有一个聚簇索引,一个索引会生成2个段,而段是以区为单位申请存储空间的,一个区默认占用1M,所以默认情况下一个只存了几条记录的小表也分配2M的存储空间,以后每次添加一个索引都要多申请2M的存储空间,这是极大的浪费。
为了考虑以完整的区为单位分配给某个段对于数据量较小的表太浪费存储空间的这种情况,InnoDB提出了一个碎片(fragment)区的概念。在一个碎片区中,并不是所有的页都是为了存储同一个段的数据而存在的,而是碎片区中的页可以用于不同的目的,比如有些页用于段A,有些页用于段B,有些页甚至哪个段都不属于。碎片区直属于表空间,并不属于任何一个段。
所以此后为某个段分配存储空间的策略是:
在刚开始向表中插入数据的时候,段是从某个碎片区以单个页面为单位来分配存储空间的。
当某个段已经占用了32个碎片区页面之后,就会申请以完整的区为单位来分配存储空间。
7、页(page)详解
页是 InnoDB 管理的最小单位,常见的有 FSP_HDR,INODE, INDEX 等类型。所有页的结构都是一样的,分为文件头(前38字节),页数据和文件尾(后8字节)。页数据根据页的类型不同而不一样。
每个空间都分为多个页,通常每页16 KiB。空间中的每个页面都分配有一个32位整数页码,通常称为“偏移量”(offset),它实际上只是页面与空间开头的偏移量(对于多文件空间,不一定是文件的偏移量)。因此,页面0位于文件偏移量0,页面1位于文件偏移量16384,依此类推。 (InnoDB 的数据限制为64TiB,这实际上是每个空间的限制,这主要是由于页码是32位整数与默认页大小的组合
数据页的内部结构
数据页的16KB大小的存储空间被划分为七个部分,分别是 文件头(File Header)、页头(Page Header)、最大最小记录(Infimum+supremum)、用户记录(User Records)、空闲空间(Free Space)、页目录(Page Directory)和文件尾(File Tailer)。