跳转至

介绍

Level 压缩风格是 rocksdb 默认的压缩风格,所以他也是用户间最常用的压缩风格。有时候用户会好奇 level 压缩在每次压缩的时候如何选择哪个文件进行压缩。在这 wiki 中,我们会在这个议题里面深入聊一下,节省你读代码的时间

步骤

从 Level 0 到最高 level,以选择第一个 level,Lb,满足这个层的分数大于 1,以此作为压缩的基础层。

决定压缩的输出层 Lo = Lb + 1

根据不同的 压缩优先选项,找到第一个需要被压缩的,优先级最高的文件。如果这个文件或者他在 Lo 的父母(就是那个 key 范围与他有交错的文件)正在被另一个压缩任务使用,跳过这个文件,使用第二高优先级的文件,知道找到 一个 候选文件。把这个文件加到压缩 输入

不断拓展输入,直到我们确定 输入文件和周围的文件 有一个“清晰分离的”边界。这保证了压缩过程中,没有部分 key 被丢失。例如,我们有五个文件,key 范围如下:

f1[a1 a2] f2[a3 a4] f3[a4 a6] f4[a6 a7] f5[a8 a9]

如果我们在第三步选择 f3,然后在第四步,我们需要从 {f3} 拓展输入到 {f2,f3,f4},因为 f2 和 f3,f3 和 f4,的边界是连在一起的。之所以两个文件会有一个相同的用户 key,是因为在 rocksdb 中,文件里的 InternalKey 会包含用户 key 原始信息,key 的类型以及序列号。所以文件可能会存储多个用户 key 相同的 InternalKey。因此,如果压缩发生,所有的用户 key 相同的 InternalKey 都需要被一起压缩。

检查当前的 输入 文件不会与任何已经在压缩的文件有交集。否则,尝试查找是否有可用的人工压缩。如果没有,放弃这次压缩挑选任务。

找出 Lo 上与 输入 文件有交集的文件,然后根据第四部的操作拓展他们,直到我们在 Lo 上有一个“清晰分离的”边界。如果他们中的任何文件正在被压缩,放弃这次压缩挑选任务。否则,把它们放入 output_level_inputs

一个可选的优化步骤。检查我们是否可以进一步增加 Lb 的输入文件,同时不用改变我们挑选的 Lo 的文件。如果这会导致 Lb 包含一些用户 key 的 InternalKey,而又排除其他的相同用户 key 的 InternalKey,我们同样会选择不拓展,导致,“一个不清晰的分离”。这可能在用户 key 分散在多个文件的时候发生。前面的描述可能让人困惑,所以我给一个例子出来解释这个优化。

考虑一下例子:

Lb: f1[B E] f2[F G] f3[H I] f4[J M] Lo: f5[A C] f6[D K] f7[L O]

如果我们最开始在第三步选择 f2,现在我们会压缩 f2(输入)以及 f6(第四步的 output_level_inputs)。但是我们可以安全地压缩 f2,f3 和 f6,而不用拓展输出 level。

输入 的文件和 output_level_inputs 的文件就是这次 level 压缩的候选文件了。