FIFO compaction 适用于低负载数据的存储(如日志),所有的文件都位于 L0。当文件总大小超过配置值 CompactionOptionsFIFO::max_table_files_size (默认值为 1GB) 时,最早的 SST 文件将会被删除。
Compaction* FIFOCompactionPicker::PickSizeCompaction(
...
std::vector<CompactionInputFiles> inputs;
inputs.emplace_back();
inputs[0].level = 0;
for (auto ritr = level_files.rbegin(); ritr != level_files.rend(); ++ritr) {
auto f = *ritr;
total_size -= f->compensated_file_size;
inputs[0].files.push_back(f);
char tmp_fsize[16];
AppendHumanBytes(f->fd.GetFileSize(), tmp_fsize, sizeof(tmp_fsize));
ROCKS_LOG_BUFFER(log_buffer,
"[%s] FIFO compaction: picking file %" PRIu64
" with size %s for deletion",
cf_name.c_str(), f->fd.GetNumber(), tmp_fsize);
// 选择文件进行 compaction 直到文件总大小小于阈值
if (total_size <=
mutable_cf_options.compaction_options_fifo.max_table_files_size) {
break;
}
}
...
}
L0 IntraCompaction
仅仅如此简单的 compaction 策略可能会因为 L0 保存了大量的 SST 文件导致查询性能急剧下降。即使有 bloom filter 的帮助,甚至可能严重到 bloom filter 的开销大到不可接受的地步。开启 CompactionOptionsFIFO.allow_compaction 参数,可以触发 L0 IntraCompaction,每次至少选取 level0_file_num_compaction_trigger 个 SST 文件进行合并,从而减少文件数量。
以 level0_file_num_compaction_trigger = 2,每个 flush 文件大小为 100MB 为例,其 compaction 过程如下:
100MB
100MB 100MB -> 200MB
100MB 200MB
100MB 100MB 200MB -> 200MB 200MB
100MB 200MB 200MB
TTL Compaction
TTL compaction 在 FIFO compaction 的基础之上,提供 SST 文件级别的过期删除功能。当 SST 的最新的 key 存在时间超过 mutable_cf_options.ttl,则该 SST 文件将会在 TTL compaction 中被删除。
Compaction* FIFOCompactionPicker::PickTTLCompaction(
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
const MutableDBOptions& mutable_db_options, VersionStorageInfo* vstorage,
LogBuffer* log_buffer) {
...
std::vector<CompactionInputFiles> inputs;
inputs.emplace_back();
inputs[0].level = 0;
// avoid underflow
if (current_time > mutable_cf_options.ttl) {
for (auto ritr = level_files.rbegin(); ritr != level_files.rend(); ++ritr) {
FileMetaData* f = *ritr;
assert(f);
if (f->fd.table_reader && f->fd.table_reader->GetTableProperties()) {
uint64_t creation_time =
f->fd.table_reader->GetTableProperties()->creation_time;
// 判断文件是否过期
if (creation_time == 0 ||
creation_time >= (current_time - mutable_cf_options.ttl)) {
break;
}
}
total_size -= f->compensated_file_size;
inputs[0].files.push_back(f);
}
}
...