自己动手写数据库(二)表的结构

来源:互联网 发布:java while写99乘法表 编辑:程序博客网 时间:2024/06/13 10:16

自己动手写数据库(二)表的结构

一点点声明

我不准备贴多少代码,因为代码实现是开发者自由去做的,我这篇文章只是为了提供一个思路或者结构,具体的实现,如果做不出来,请多多练习基本功。
另外我这篇文章讲的是以行为储存的,列式储存的数据库类似。

表的逻辑模型

我们知道,在关系型数据库中,数据是以表的形式来储存的,那么我们也应该实现一个表的数据结构,比如下面这样(伪代码):

Table {    Row[]       row,    String[]    columnNames}

里面要有一个存储行的可变数组(可以用C++的向量等实现),要有一个列名的可变数组,因为我们select出的表,每列是有一个名字的,
当然我们还有一些临时表,可能不需要列名,这个在于开发者自己的实现。
行,是Value的数组Row <=> Value[],而Value的结构大概类似下面这样:

Value {    char[]      raw,    unsigned    type,}

因为Value需要支持多种类型,所以需要一个type字段,type标识数据类型,方便处理和输出时进行判断,raw字段用来储存各种类型对应的二进制存储,
这里举个int的例子,比如储存18056这个数,那么我们将其二进制化,然后按高位存高位,低位存低位储存即可。可以参考计算机中的各种类型的储存方式:
比如浮点数。

表的物理模型

但是,上面的模型仅仅能被称为逻辑模型,而真正要储存这些表,仅仅上面的数据是不够的,比如:我如何知道我的表有哪些字段,哪些字段上面建立了索引。
所以,实际储存的表需要类似于下面的结构:

Table {    String  name,    Field[] fields,    Page*   firstPage,    Page*   lastPage,    Index*  primaryKey}

储存了表的名字,表的字段集(Fields),还有表的主键(primaryKey),以及表实际存储的页(Page),Index索引类型,我们放在下一篇进行说明,
Field结构作为储存字段信息,它的结构类似如下:

Field {    String      name,    bool        fixedSize,    unsigned    size,    unsigned    type,    Index*      index}

存储字段名,字段是否是定长字段(比如整数,浮点数,和定长字符串是定长的,变长字符串是变长的),size用于描述定长类型的长度(储存为二进制的字节长度)
type标识字段类型,index标识此字段上是否有索引,索引是什么。其他需要支持的属性也可以加在这个结构中,比如unique之类。
那么表中的数据如何在磁盘中储存呢,我们是用链表来管理储存单元Page,每个页由以下的方式存储:

[Table Pointer(8Bytes)] [Prev Page Pointer(8Bytes)] [Next Page Pointer(8Bytes)] [Free Positon(8Bytes)] [Reserved (32Bytes)][Skip Bytes(8Bytes)] [Size (4Bytes)] [Field Data (Size Bytes)] ...

第一行是页头,页头存储了页所属表的指针,前后页的指针,该页的空闲空间偏移量的指针(每次写数据,将偏移量指针向后移动)。64个字节的页头结束后,是数据区
,数据区按行存储,每行先是一个8字节的标识,表明该行是否已被标记删除(我们在删除时,仅仅标记这一行被删除,而不是真正的去掉这一行并把后面的数据都搬到前面
,因为这样做代价太大了,不仅要复制数据,还要维护页链表,我们采用当空闲时再进行重构的的方法),如果为0,则未被删除,如果不为0,则为该行记录的长度,即到下一条
记录还需要多少偏移。skip字段之后是表的所有列,如果该列是定长的,我们直接储存数据,如果是变长的,先用4字节储存长度,再储存数据。
可能有人会有疑问,你将指针存在磁盘里面?那么你下次启动岂不是全部无效了?这个问题,我们留在恢复系统中说明,包括表说明的存储,敬请期待~

0 0
原创粉丝点击