个人理解: delete a range of keys 就删除一定范围内的key, 比如删除所有以
userid
为前缀的keys
简单粗暴的方法
一种显而易见的方式就是遍历DB, 遇到特定范围里的key,直接调用Delete
就可以了,这种方法适合于要删除的keys数量小的情况。另一方面, 这种方法有两个显著问题:
- 问题一: 不能立刻收回资源,得等compaction完成后在能真正收回资源
- 问题二: 大量的tombstones(也就是标记为del的key) 会减缓迭代器效率。
问题一的解决方法
- 对要删除range key使用DeleteFilesInRange, 这个方法会直接删除只包含range keys的文件, 对于大块的range, 这个方法可以直接回收资源,值得注意的是:
- 即使做完这个操作,一些在range keys范围内的数据依然存在于db中, 这个时候还需要一点的其他的opera
- 这个操作直接忽视了snapshots, 导致可能通过snapshot 读不到本该可以读到的数据
-
compaction filter + compactRange
, 一旦写个compaction filter, 做完compaction的时候,该删除的数据也没了。 在使用的时候, 可以设置CompactionFilter::IgnoreSnapshots = true
, 这样的话, 就可以保证删除range keys,否则的话, 不能删除所有的keys , 这种方法也能很好的回收资源, 唯一的缺点是可能会增加I/O压力 - 上述两种方法各有优缺点, 其实可以把他们综合起来,
DeleteFilesInRange + compaction filter + compactRange
问题二的解决方法
这个问题比较难解决,可以仍然沿用问题一的解决方法。 但是,对大范围的range, 这种方法很有效, 如果range范围小,这种方法代价太高: 范围小导致DeleteFilesInRange可能并不能删除文件, CompactRange会对所有的包含delete range中的SST文件进行compaction,导致代价太高,这里有两种方法减轻这种代价
- 如果你从来不改写已经存在的keys,使用
DB::SingleDelete
而不是Delete就可以很快消灭tombstones, 这种Tombstone可以很快被清除而不是被一直推到last level (笔者这里这不是很清楚, 待会看看) - 使用
NewCompactOnDeletionCollectorFactory()
, 可以在有大量tombstones的时候加快compaction
网友评论