C语言从零实现SQLite数据库(七)

SQLite的核心思想是使用B-tree实现表和索引的存储。为什么B-tree这种数据结构更适合于数据库呢?

  • 搜索数据非常快(时间消耗随着数据规模的增大呈对数级增长)
  • 对于已经找到的值,插入/删除操作非常快(每次插入/删除后再平衡时间恒定)
  • 能快速遍历值(与哈希表不同)

B-tree

B-tree的结构与传统的二叉树不同(“B”可能代表其发明人的名字,也可能表示“平衡”的意思)。下面是B-tree的示意图:
B-tree实例
与二叉树不同,B-tree的每个节点不只有两个子节点。每个节点最多可以有m个子节点,其中m称为树的“阶数”。为了让树保持最大程度的平衡,我们也会规定节点必须有至少m/2个子节点(向上取整)。下面是一些特殊情况:

  • 叶子节点没有子节点
  • 根节点的子节点数可以比m少,但是必须至少有两个子节点
  • 如果根节点是一个叶子节点(是整棵树中唯一的节点),那么它也不能有子节点

上图的B-tree是SQLite用来存储索引的。如果想存储表,SQLite使用的是B-tree的变种,叫B+ tree。

B-treeB+ tree
Pronounced“Bee Tree”“Bee Plus Tree”
Used to storeIndexesTables
Internal nodes store keysYesYes
Internal nodes store valuesYesNo
Number of children per nodeLessMore
Internal nodes vs. leaf nodesSame structureDifferent structure

在实现索引之前,我们只讨论B+ tree,但是我们也把它叫做B-tree。

有子节点的节点叫做“中间”节点。中间节点和叶子节点的结构不同:

For an order-m tree…Internal NodeLeaf Node
Storeskeys and pointers to childrenkeys and values
Number of keysup to m-1as many as will fit
Number of pointersnumber of keys + 1none
Number of valuesnonenumber of keys
Key purposeused for routingpaired with value
Stores valuesNoYes

B-tree元素插入示例

让我们通过一个示例来看看B-tree在插入元素时是如何变化的。为了让事情变得简单,我们把B-tree的阶数定为3,这意味着:

  • 每个中间节点最多有3个子节点
  • 每个中间节点最多有2个键
  • 每个中间节点最少有2个子节点
  • 每个中间节点最少有1个键

一个空的B-tree只有一个节点,即根节点。根节点开始时作为叶子节点没有键值对:
空B-tree
每当我们插入一组键值对,它们都会按大小顺序存放在叶子节点中。下图是插入两组键值对后B-tree的情况:
单节点B-tree
假设叶子节点的容量是两组键值对。此时,我们再插入第三组键值对,叶子节点会拆分成两个节点,同时每个节点只拥有原先一半的键值对。随后,生成一个新的中间节点,之前两个节点将成为其子节点。该中间节点现在就成为了根节点。
双层B-tree
此时,中间节点有1个键和两个指向子节点的指针。如果想查找小于等于5的键,我们可以从左子节点中找。如果想查找大于5的键,我们可以从右子节点中找。

现在,让我们插入“2”这个键。我们先查它应该存放在哪个叶子节点中,此时我们会找到左子节点。但是当前该节点已经满了,因此我们拆分左子节点,并在其父节点中创建一个新的键。
4个节点的B-tree
让我们继续添加键“18”和“21”。此时,我们又到了必须再次分割的子节点的时刻,但是父节点中已经没有空间再容纳新的键和指针了。
中间节点没有多余空间
解决办法是将根节点拆分为两个中间节点,然后创建新的根节点作为它们的父节点。
三层B-tree

总结

从上面的示例中我们可以得出:

  • 只有在拆分根节点时树的深度才会增加
  • 每个叶节点具有相同的深度和近似数量的键值对,因此树能够保持平衡,从而实现快速搜索

在我们实现B-tree的插入功能之前,暂时先不讨论如何从树中删除键。

当我们实现B-tree时,每个节点对应一页,根节点存放在第0页。指向子节点指针可以简单地用包含该子节点的页码来代替。

下一节我们将开始实现B-tree!

原文链接:Let’s Build a Simple Database: Part 7 - Introduction to the B-Tree

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值