刚才我们提到 B+ 树随机写入慢的问题,对于这个问题,我们现在来思考一下优化想法。操作系统对 磁盘的 读写是以块为单位 的,我们能否以块为单位写入,而不是每次插入一个数据都要随机写入磁盘呢?这样是不是就可以大幅度减少写入操作了呢?
LSM 树就是根据这个思路设计了这样一个机制:当数据写入时,延迟写磁盘,将数据先存放在内存中的树里,进行常规的存储和查询。当内存中的树持续变大达到阈值时,再批量地以块为单位写入磁盘的树中。因此,LSM 树至少需要由两棵树组成,一棵是存储在内存中较小的 C0 树,另一棵是存储在磁盘中较大的 C1 树。简单起见,接下来我们就假设只有 C0 树和 C1 树。
LSM 树由至少 2 部分组成:内存的 C0 树和磁盘的 C1 树
C1 树存储在磁盘中,因此我们可以直接使用 B+ 树来生成。那对于全部存储在内存中的 C0 树,我们该如何生成呢?在上一讲的重点回顾中我们分析过,在数据都能加载在内存中的时候,B+ 树并不是最合适的选择,它的效率并不会更高。因此,C0 树我们可以选择其他的数据结构来实现,比如平衡二叉树甚至跳表等。但是为了让你更简单、清晰地理解 LSM 树的核心理念,我们可以假设 C0 树也是一棵 B+ 树。
那现在 C0 树和 C1 树就都是 B+ 树生成的了,但是相比于普通 B+ 树生成的 C0 树,C1 树有一个特点:所有的叶子节点都是满的。为什么会这样呢?原因就是,C1 树不需要支持随机写入了,我们完全可以等内存中的数据写满一个叶子节点之后,再批量写入磁盘。因此,每个叶子节点都是满的,不需要预留空位来支持新数据的随机写入。