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压缩的候选文件了。