如果我们有大量的记录,那么表空间中页的数量就会非常的多,为了更好的管理这些页,设计者又提出了区的概念。对于16KB的页来说,连续的64个页(连续的)就是一个区,也就是说一个区的大小为1MB。(256个区被划分成一个组)
通过页其实已经形成了完整的功能,我们查询数据时这样沿着双向链表就可以查到数据,但是页与页之间在物理位置上可能不是连续的,如果相隔太远,那么我们从一个页移动到另一个页的时候,磁盘就要重新定义磁头的位置,产生随机IO,影响性能,所以我们才要引入区的概念,一个区就是物理位置连续的64个页。区是属于某一个段的(或者是混合)。
正常情况下,我们检索都是在叶子节点的双向链表进行的,也就是说我们会把区进行区分,如果不区分把叶子节点和非叶子结点混在一起,那么效果就会打大折扣,所以对于一个索引B+树来说,我们区别对待叶子节点的区和非叶子节点的区,并把存放叶子节点的区的集合称为一个段把存放非叶子节点区的集合也称为一个段,所以一个索引会生成两个段:叶子节点段和非叶子节点段。
默认情况下,假如我们新建一个索引就会生成两个段(叶子节点段和非叶子节点段),而一个段中至少包含一个区,也就是需要2MB的空间,假如我们这个表压根没有多少数据,那么一次就要申请2MB的空间明显是浪费的。为了解决这个问题,设计者提出了碎片区的概念,碎片区中的页可能属于不同的段,也可以用于不同的目的,至于如何控制应不应该给一个段申请专属的区,会进行以下控制:
我们现在知道表空间是由若干个区组成的,这些区可以分成以下的4中类型:
为了管理各种各样的区,设计者提成了一个XDES Entry结构。
当我们需要某一个类型的XDES Entry时候,如何快速的拿到,这就跟XDES Entry形成的链表有关了,对于属于表的三种类型 FREE,FREE_FRAG,FULL_FRAG,会生成三个链表:
我们前面说了FREE,FREE_FRAG,FULL_FRAG三种类型的链表,这三种类型是针对碎片区的,而对于段专属的区类型FSEG,也会形成三种类型的链表,这三个链表属于段,存在段结构中。
段不是一个物理上连续的空间,而是一个逻辑上的概念,一个段包含若干零散的页面还有自己专属的FSEG区,这些FSEG区形成FREE, NOT_FULL, FULL三种链表保存在段上,像XDES Entry一样,设计者也给段定义了一个结构INODE Entry。
XDES Entry保存了有关区的消息,大小为40字节,而我们说一个区大小是1MB,由64个页组成,16KB * 64 = 1024KB 刚好1MB,也就是没有额外的40字节来存储XDES Entry了,那这些XDES Entry到底是存放在哪的?
前面我们有说过组的概念,组由256个区组成。表空间由组组成,组中包含了XDES Entry等信息。
以上我们可以理解为一个表空间的组成,有组1,组2,我们之前所说的各种信息,都会保存在每一组的第一个区中的前面几个页里面。而作为表空间的第一个组,则要另外保存与表相关的信息。
与FSP_HDR页一样,只是没有File Space Header。
当发生记录的增删改时,聚餐索引会发生相应的变化,如果也二级索引的B+树也要发生相应的调整,而这些对应的页往往都不在内存中,如果要修改必须发生磁盘IO,把对应的二级索引页也给读到内存中进行修改,这样就增加了IO的次数,影响性能。
IBUF_BITMAP页的作用就是缓存这些操作,等到下一次MySQL刚好把这些要修改的页读取到内存的时候,顺便修改。
我们之前分析过,一个索引有两个段,一个段会对应INODE Entry结构,这个页就是用来保存这个表空间所有的INODE Entry结构的。