每一个 XDES Entry 结构对应表空间的一个区,虽然一个 XDES Entry 结构只占用40字节,但你抵不住表空间的区的数量也多啊。在区的数量非常多时,一个单独的页可能就不够存放足够多的 XDES Entry 结构,所以我们把表空间的区分为了若干个组,每组开头的一个页面记录着本组内所有的区对应的 XDES Entry 结构。由于第一个组的第一个页面有些特殊,因为它也是整个表空间的第一个页面,所以除了记录本组中的所有区对应的 XDES Entry 结构以外,还记录着表空间的一些整体属性,这个页面的类型就是我们刚刚说完的 FSP_HDR 类型,整个表空间里只有一个这个类型的页面。除去第一个分组以外,之后的每个分组的第一个页面只需要记录本组内所有的区对应的 XDES Entry 结构即可,不需要再记录表空间的属性了,为了和 FSP_HDR 类型做区别,我们把之后每个分组的第一个页面的类型定义为 XDES ,它的结构和 FSP_HDR 类型是非常相似的:
与 FSP_HDR 类型的页面对比,除了少了 File Space Header 部分之外,也就是除了少了记录表空间整体属性的部分之外,其余的部分是一样的。
根据表空间的图,每个分组的第二个页面的类型都是IBUF_BITMAP,这种类型的页里面记录了Change buffer。
一个INODE类型的页面是由这几部分构成的:
名称 | 中文名 | 占用空间大小 | 简单描述 |
File Header | 文件头部 | 38字节 | 页的一些通用信息 |
List Node for INODE Page List | 通用链表节点 | 12 字节 | 存储上一个INODE页面和下一个INODE页面的指针 |
INODE Entry | 段描述信息 | 16128 字节 | |
Empty Space | 尚未使用空间 | 6 字节 | 用于页结构的填充,没啥实际意义 |
File Trailer | 文件尾部 | 8 字节 | 校验页是否完整 |
每个 INODE Entry 结构占用192字节,一个页面里可以存储 85 个这样的结构。
一个表空间中可能存在超过85个段,所以可能一个 INODE 类型的页面不足以存储所有的段对应的 INODE Entry 结构,所以就需要额外的 INODE 类型的页面来存储这些结构。还是为了方便管理这些 INODE 类型的页面,于是这些INODE类型的页面串联成两个不同的链表:
SEG_INODES_FULL 链表:该链表中的 INODE 类型的页面中已经没有空闲空间来存储额外的 INODE Entry 结构了。
SEG_INODES_FREE 链表:该链表中的 INODE 类型的页面中还有空闲空间来存储额外的 INODE Entry 结构了。
每当我们新创建一个段(创建索引时就会创建段)时,都会创建一个 INODE Entry 结构与之对应,存储 INODE Entry 的大致过程就是这样的:
一个索引会产生两个段,分别是叶子节点和非叶子节点段,每个段都会对应一个INODE Entry结构。
Page Header部分 | ||
名称 | 占用空间大小 | 描述 |
PAGE_BTR_SEG_LEAF | 10 字节 | B+树叶子段的头部信息,仅在B+树的根页定义 |
PAGE_BTR_SEG_TOP | 10 字节 | B+树非叶子段的头部信息,仅在B+树的根页定义 |
其中的 PAGE_BTR_SEG_LEAF 和 PAGE_BTR_SEG_TOP 都占用10个字节,它们其实对应一个叫 Segment Header 的结构,该结构图示如下:
各个部分的具体释义如下:
名称 | 占用字节数 | 描述 |
Space ID of the INODE Entry | 4 | INODE Entry结构所在的表空间ID |
Page Number of the INODE Entry | 4 | INODE Entry结构所在的页面页号 |
Byte Offset of the INODE Ent | 2 | INODE Entry结构在该页面中的偏移量 |
PAGE_BTR_SEG_LEAF 记录着叶子节点段对应的 INODE Entry 结构的地址是哪个表空间的哪个页面的哪个偏移量, PAGE_BTR_SEG_TOP 记录着非叶子节点段对应的 INODE Entry 结构的地址是哪个表空间的哪个页面的哪个偏移量。这样子索引和其对应的段的关系就建立起来了。不过需要注意的一点是,因为一个索引只对应两个段,所以只需要在索引的根页面中记录这两个结构即可。