Rocksdb数据库---levle compaction

官网原文:https://github.com/facebook/rocksdb/wiki/Leveled-Compaction
如有翻译不当或错误,请给出意见,
如果需要转载,请注明来源。谢谢。

Structure of the files

rocksdb 把磁盘上的文件组织为多层,我们称之为level1,levle2,或者L1,L2…
比较特殊的levle0层包含的文件是从memtable 中flushed过来 的,每个层的数据按照以下的方式组织排序

非0 level上的数据,被分片保存在大量不同 的sstable 文件中。

每个level的文件都是整体有序的,因为文件内部的key是有序的。为了确定一个key的位置,我们
先根据每个文件的start/end key对所有文件进行二分查找来确定哪些文件可能包含key。
再通过二分查找在候选的文件中定位key的准确位置,这是一次对一个level上所有文件的二分查找的过程。

所有非零的levle 都有指定的大小,我们进行compaction 的目的就是使数据大小维持target_size 之下,,数据的大小经常会呈指数级增长,

Compactions

当L0的文件数量达到level0_file_num_compaction_trigger的值时,触发L0和L1的合并。通常必须将所有L0的文件合并到L1中,因为L0的文件的key是有交叠的(overlapping)。

当L0 compaction完成后,L1的文件总size或者文件数量可能会超过阈值

在这种情况下,我们会从L1至少选择一个文件,合并到L2中key有交叠的文件中。

如果结果导致push 到下一个level 的大小也超过了限制,我们会按照之前做的一样,选择一个文件,并且把它merge到下一个levle.

接下来

接下来

如果需要,很多次的数据compaction 都可以并行执行

max_background_compactions控制了并行compaction的最大数量。
L0向L1的compaction不可以与其他level compaction并行。这可能成为整体compaction速度的瓶颈,可以通过设置max_subcompactions来加速L0到L1的compaction。
在这种情况下,我们会尽可能的尝试把数据文件分割揭开,然后使用大量的线程去执行compaction

compaction picking

当多个level都满足触发compaction的条件,rocksdb通过计算得分来选择先做哪一个level的compaction。

  • 对于非0 level,score = 该level文件的总长度 / 阈值。已经正在做compaction的文件不计入总长度中。
  • 对于L0,score = max{文件数量 / level0_file_num_compaction_trigger, L0文件总长度 / max_bytes_for_level_base} 并且 L0文件数量 > level0_file_num_compaction_trigger。
    我们 通过比较每个level的得分大小,选择得分最高的优先做coompaction

compaction阈值

  • 当level_compaction_dynamic_level_bytes为false
    L1 触发阈值:max_bytes_for_level_base
    Target_Size(Ln+1) = Target_Size(Ln) * max_bytes_for_level_multiplier
    * max_bytes_for_level_multiplier_additional[n].max_bytes_for_level_multiplier_additional

例如:
max_bytes_for_level_base = 16384
max_bytes_for_level_multiplier = 10
max_bytes_for_level_multiplier_additional = 1
那么每个level的触发阈值为 L1, L2, L3 and L4 分别为 16384, 163840, 1638400, and 16384000

  • 当level_compaction_dynamic_level_bytes为true
    最后一个level的文件长度总是固定的。
    上面level触发阈值通过公式计算:Target_Size(Ln-1) = Target_Size(Ln) / max_bytes_for_level_multiplier
    如果计算得到的值小于 max_bytes_for_level_base / max_bytes_for_level_multiplier, 那么该level将维持为空,L0做compaction时将直接merge到第一个有合法阈值的level上。
    例如:
    max_bytes_for_level_base = 1G
    num_levels = 6
    level 6 size = 276G
    那么从L1到L6的触发阈值分别为:0, 0, 0.276G, 2.76G, 27.6G,276G。

这样分配,保证了稳定的LSM-tree结构。并且有90%的数据存储在最后一层,9%的数据保存在倒数第二层。

你可能感兴趣的:(linux,块设备驱动)