自己动手写数据库(二)表的结构
来源:互联网 发布: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字节储存长度,再储存数据。
可能有人会有疑问,你将指针存在磁盘里面?那么你下次启动岂不是全部无效了?这个问题,我们留在恢复系统中说明,包括表说明的存储,敬请期待~
- 自己动手写数据库(二)表的结构
- 自己动手写俄罗斯方块(二)
- 自己动手写操作系统(二)
- 自己动手写PHP框架(二)
- 自己动手写操作系统(二)
- 自己动手写操作系统(二)
- 自己动手写俄罗斯方块(二)
- 自己动手写操作系统(二)
- 自己动手写 android 数据库(1)
- 自己动手写 android 数据库(2)
- 自己动手写DB数据库框架(增)
- 自己动手写数据库
- 自己动手写Android数据库框架
- ROS(二)自己动手写一个简单的发布(Publisher)、订阅(Subscriber)程序
- 自己动手写一个简单的Shell之二:运行程序
- 自己动手写操作系统二(编写内核Hello World 教程)
- 自己动手写C语言格式化输出函数(二)
- 自己动手写web服务器二(处理get请求)
- JS实现跟随
- 编译内核fatal error:openssl/名单.h:No such file or directory
- 轻量级图形报表工具JSCharts中文开发文档
- Linux 下设置Mysql远程连接
- 欢迎使用CSDN-markdown编辑器
- 自己动手写数据库(二)表的结构
- Python 文件I/O
- LeetCode345—Reverse Vowels of a String
- 关于安卓应用执行的内部机制分析
- 无法将文件“..\obj\*.dll”复制“..\bin\*.dll”,对路径“..\bin\*.dll”的访问被拒绝
- 一种简单的图像显著性计算模型
- android Spinner控件详解
- cuDNN API 演化 (二)—— Deprecation 策略
- 按钮发送验证码等待时间效果——定时器setInterval使用