在 RocksDB 中,有配置项 max_subcompactions
,在 Level Compaction Style 中,max_subcompactions
在两种情况下生效:
- L0 + L1 -> L1 compaction (更准确地说 output 不一定是 L1,但 input 一定有 L0)
- Manual Compaction
当 num_subcompact > 1
时,不同的 subcompact 会在多个线程中并发执行,对于覆盖了多个 subcompact 的 SST 文件,会在这多个 subcompact 线程中分别读取相应的部分,如果是发生在 DB 结点上对热数据的 compact,这没什么问题,因为读文件要通过操作系统 PageCache,即便多个线程访问,也有很大概率会命中 PageCache。
但是,如果 compact 的 input sst 是冷数据,PageCache 的利用率会降低!
这是因为:Compact 对 SST 文件是顺序访问,对于 subcompact 边界上的 SST 文件,后面一个 subcompact 最先访问的文件,在前一个 subcompact 是最后访问,此时之前加载到 PageCache 中的数据,可能已经被 evict 出去了!特别是对于 Topling SST,预加载的文件内容比例较大(不像 BlockBasedTable 只需加载 BlockIndex)。
Compact input sst 是冷数据分两种情况:
- DB 结点上对冷数据的 Compact
- 分布式Compact,对 Compact 结点而言,所有 SST 都是冷数据
所以,在 RocksDB 中,决定是启用 subcompact 的规则是非常合理的,因为 Manual Compact 用户可以用非0值来设置 CompactRangeOptions.max_subcompactions
以覆盖 DBOptions.max_subcompactions
。
max_level1_subcompactions
在 ToplingDB 分布式Compact 中,即便是 Manual Compact,我们也不希望启用 subcompact,那就只能在用户代码中设置 CompactRangeOptions.max_subcompactions = 1
,而我们希望用户代码尽量不用修改,所以,我们新加了一个选项:DBOptions.max_level1_subcompactions
。
它默认情况下等于 DBOptions.max_subcompactions
,但是不管在任何情况下,它只影响 start_level = 0 的 Compact。