从零实现一个数据库(DataBase) Go语言实现版 2.索引

英文源地址

键值对存储和关系型数据库

虽然一个关系型数据库支持多种类型的查询, 几乎所有查询都可以分解为三种类型的磁盘操作.

  1. 扫描所有的数据集(不使用索引)
  2. 点查询: 按指定key索引查询
  3. 范围查询: 按范围查询索引(索引是排序的)

数据库索引大多数关于范围查询和点查询, 而且很容易看出范围查询只是点查询的一个超集.如果我们提取数据库索引的功能, 那么创建键值存储就很简单了.但关键是数据库系统可以建立在KV存储之上.
在尝试关系型数据库之前, 我们将构建一个KV键值对存储, 但我们先探索一下我们的选项.

哈希表/散列表

哈希表/散列表在设计一个通用的kv存储时是首先被排除在外的.主要原因是排序-许多现实世界的应用需要分类和排序.
然而, 在专门的应用中可能会使用哈希表/散列表.使用哈希表的另一个头痛的问题是大小调整操作.初始调整大小复杂度在O(n), 会导致磁盘空间和IO的突然增加.是有可能做到增量地调整哈希表的, 但这会增加复杂度.

B-Trees B树

平衡二叉树可以在Ologn复杂度内被查询或更新, 还可以区间查询.一个B树大致是一个平衡的n叉树.为什么使用n叉树代替一个二叉树?有以下几种原因:

  1. 减少空间开销.二叉树的每个叶子节点都可以通过从父节点的一个指针到达, 而父节点可能也有自己的父节点. 平均下来, 每个叶子节点需要1-2个指针.这与B树相反.在b树中, 叶子节点中的多个数据共享一个父节点.n叉树也更短, 指针上浪费的空间更少.
  2. 在内存中更快.由于现代CPU内存缓存和其他因素, n叉树可以比二叉树更快, 即使它们的大O复杂度是相同的.
  3. 更少的磁盘IO.B树更短, 这意味着更少的磁盘搜索.磁盘IO的最小大小通常是内存页面的大小(可能是4k).操作系统将填满整个4k页空间, 即使你读取较小的大小. 如果我们利用4k页中的所有信息(通过选择至少一个页面的节点大小), 这是最优的.

我们在接下来的文章中使用B树, 但B树不是唯一的选择.

LSM树

Log-structured merge-tree日志结构merge树.下面是LSM树操作的高级描述.

如何查询

  1. 一个LSM树包含多级数据
  2. 每个级别被排序并分成多个文件
  3. 点查询从顶层开始, 如果没有找到关键字, 则继续搜索到下一层
  4. 范围查询合并所有级别的结果, 级别越高, 合并时优先级越高.

如何更新

  1. 更新一个键时, 首先从顶层将键插入到文件.
  2. 如果文件大小超过阈值, 将其与下一个级别合并.
  3. 文件大小阈值随着级别的增加呈指数增长, 这意味着数据量也呈指数增长.

让我们分析下这如何工作的.对于查询:

  1. 每个级别都是排序的, 键可以通过二分搜索找到, 范围查询只是顺序的文件IO, 它是高效的.

对于更新:

  1. 顶级文件的大小很小, 因此插入顶级文件只需要少量IO.
  2. 数据最终合并到较低的级别. 合并是顺序IO, 这是一个优势.
  3. 更高的级别会更频繁地触发合并, 但合并也更小.
  4. 将文件合并到较低级别时, 范围相交地较低级别文件将被合并地结果(可以是多个文件)替换. 我们可以看到为什么级别被分割成多个文件-减少合并的大小.
  5. 合并可以在后台完成.但是, 低级合并可能会突然导致高IO使用率, 从而降低系统性能.

读完本书后, 读者可以尝试使用lsm树来代替b树, 并比较b树和lsm树地优缺点.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值