存单点1.5 过度点:页与索引

86 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天

上次说到了页

然而记录本身也不是简简单单地放进去的

这些记录也需要某种规则来进行管理

也就是说,**页本身也是有结构的:**文件头部、页面头部、最小记录和最大记录、用户记录、空闲空间、页目录、文件尾部

而在这个里面,我们从最小记录和最大记录、用户记录看起,他们与记录最息息相关

最小记录和最大记录、用户记录

用户记录

用户记录的存放也是有组织的

  • 通过 记录头信息 中的 next_record(下一个记录记录头信息中next record的相对位置),将记录连接起来,形成单向链表
    • 主键顺序从小到大连接
  • 删除的时候,只是修改标记位、next record为0以及记录链表
  • 新插入数据时,会重新填充被标记删除的记录

最小记录和最大记录

实际上用户记录的heap_no(页位置)是从2开始的

  • 0为最小记录
  • 1为最大记录
  • 同时最小记录为链表头,最大记录为链表尾

这两个记录都只有记录头信息和一个固定数据在数据区

页目录

查询的时候,如果沿着链表查,复杂度为O(n),着实有点慢

这个时候需要个方法来加速查找

页目录出现了

原理

实际上就是把记录进行分组

分组主键最大记录为分组leader

  • 每个分组记录数在5-8之间
  • 分组记录数会放在该分组leader的n_owned字段
  • 最小记录自己为一个分组

将分组leader的地址偏移记录到页目录中

形成一个分组地址集合后,可以采用二分查找的方式加快查询速度

形成过程

  • 找到最近那个主键比自己大的分组leader,进入其分组
    • 分组leader的n_owned++
  • 如果该分组记录数==8
    • 分裂成 4 + 5 的两个分组(包含新纪录)
    • 新分组的leader地址记录到页目录中

File Header

每一个页都需要一个部分来表示当前页的状态

比如有几条记录、页目录状态啥的\

通用页的这些描述被称为FileHeader(文件头部) ,固定38个字节

数据页有自己特殊的描述,被称为PageHeader(页头部)

重要的属性

  • FIL_PAGE_SPACE_OR_CHKSUM:当前页所有东西的校验和,4个字节
  • FIL_PAGE_OFFSET:页号,类似记录主键
  • FIL_PAGE_TYPE:页类型,如上述的数据页
  • FIL_PAGE_PREV和FIL_PAGE_NEXT:类似记录中的next_record,分别为上一页、下一页的页号

File Trailer

也是一个通用页属性

8字节,前4个字节也是校验和,后4个字节为最后修改时对应的日志序列位置(LSN)

  • 当记录写入时被中断(数据同步出错),FileTrailer与FileHeader的校验和会不一致