MemTable

MemTable是一个内存中的数据结构,在将数据刷新到SST文件之前保存数据。它同时提供读和写功能——新的写操作总是将数据插入到memtable中,读操作必须在从SST文件中读取之前查询memtable,因为memtable中的数据是较新的。 一旦memtable被填满,它就变成不可变的,并被一个新的memtable替换。后台线程将memtable的内容刷新到一个SST文件中,然后可以销毁memtable.

影响memtable行为的最重要选项是:

  • memtable_factory: memtable的工厂对象。通过指定工厂对象,用户可以更改memtable的底层实现,并提供特定于实现的选项。
  • write_buffer_size: 单个memtable的大小。
  • db_write_buffer_size: 跨列族的memtables的总大小。这可以用来管理memtables使用的总内存。
  • write_buffer_manager: 用户可以提供自己的写缓冲区管理器来控制整个memtable内存使用情况,而不是指定memtable的总大小。覆盖db_write_buffer_size。
  • max_write_buffer_number: 内存中内存表在刷新到SST文件之前累积的最大数量。

memtable的默认实现基于skiplist。除了默认的memtable实现之外,用户还可以使用其他类型的memtable实现,例如HashLinkList、HashSkipList或Vector来加速一些查询。

Skiplist MemTable

基于skiplist的memtable在读写、随机访问和顺序扫描方面都提供了良好的性能。此外,它还提供了一些其他memtable实现目前不支持的其他有用特性,比如并发插入( https://github.com/facebook/rocksdb/wiki/MemTable#concurrent-insert )和带提示的插入 ( https://github.com/facebook/rocksdb/wiki/MemTable#insert-with-hint )。

HashSkiplist MemTable

顾名思义,HashSkipList在哈希表中组织数据,每个哈希桶都是一个跳转列表,而HashLinkList在哈希表中组织数据,每个哈希桶都是一个排序的单链表。 这两种类型都是为了在执行查询时减少比较次数而构建的。一个很好的用例是将它们与可表的SST格式结合起来,并将数据存储在RAMFS中。

当执行查找或插入key时,使用选项检索目标密钥的前缀。前缀提取器,用于查找散列桶。在散列桶中,所有的比较都是使用整个(内部)键来完成的,就像基于SkipList的memtable一样。

基于哈希的memtables的最大限制是,跨多个前缀进行扫描需要复制和排序,这非常慢,而且内存开销很大。

Flush

有三种情况可以触发memtable刷新:

  1. 1.写入后Memtable大小超过write_buffer_size
  2. 2.所有列族的memtable总大小都超过db_write_buffer_size,或者write_buffer_manager表示刷新。在这种情况下,最大的memtable将被刷新。
  3. 3.WAL文件大小超过max_total_wal_size。在这个场景中,包含最老数据的memtable将被刷新,以便清除包含来自这个memtable的数据的WAL文件。

因此,可以在memtable满之前刷新它。这是生成的SST文件可以小于相应memtable的原因之一。 压缩是使SST文件小于相应memtable的另一个因素,因为memtable中的数据是未压缩的。

Concurrent Insert

如果不支持对memtables的并发插入,则多个线程对RocksDB的并发写操作将依次应用于memtable。 默认情况下启用了并发memtable insert,可以通过allow_concurrent_memtable_write选项关闭它,不过只有基于skiplist的memtable支持该特性。

Insert with Hint

In-place Update

Comparison

MemTable 类型 SkipList 跳表 HashSkipList HashLinkList Vector 向量
优化用例 一般 特定键前缀中的范围查询 范围查询位于特定的键前缀内,每个前缀只有少量行 随机写大量工作负载
索引类型 二分查找 哈希+二分查找 哈希+线性查找 线性查找
完全的支持订购全数据库扫描? 自然 非常昂贵(复制和排序以创建临时的完全有序视图) 非常昂贵(复制和排序以创建临时的完全有序视图) 非常昂贵(复制和排序以创建临时的完全有序视图)
内存开销 平均(每个条目有多个指针) High(散列桶+非空桶的跳过列表元数据+每个条目有多个指针) Lower (哈希桶+每个条目的指针) Low低(向量末尾的预分配空间)
MemTable刷新 快速与恒定的额外内存 速度慢,临时内存使用率高 速度慢,临时内存使用率高 慢与恒定的额外内存
并发插入 支持 不支持 不支持 不支持
插入与提示 支持(如果没有并发插入) 不支持 不支持 不支持