-
Notifications
You must be signed in to change notification settings - Fork 6
ToplingZipTable
在 ToplingZipTable 中,有两个核心概念:CO-Index 和 PA-Zip
- CO-Index: 即 Compressed Ordered Index,把一个类型为 ByteArray 的 Key,映射到一个整数 ID,这个 ID 用来访问 PA-Zip 中相应的那条 Value。
- PA-Zip: Point Accessible Zip,可以看做是一个抽象的 array,核心功能是把 ID 作为抽象数组的下标,去访问该抽象数组的元素,当然,这些元素都是压缩存储的。
CO-Index 和 PA-Zip 一起,构成一个逻辑上的 map<Key, Value>
在这里,Key 是 RocksDB 中的 InternalKey: {UserKey, Seq, OpType} 三元组。
CO-Index 在 ToplingDB 中最典型的实现是 NestLoudsTrie,PA-Zip 在 ToplingDB 中最典型的实现是 DictZipBlobStore,两者都是内存压缩的,也就是说,它们在内存中的形态是压缩的,所有的搜索、读取操作都是在内存压缩的形态上执行的。并且 CO-Index + PA-Zip
的压缩率很高,远胜于 BlockBasedTable + zstd。
ToplingZipTable 压缩的计算开销较大(大约是 zstd 的两倍),所以,在 ToplingDB 中,主要是将它通过 DispatchTable 配置在 LSM 的较下层,并通过分布式Compact执行压缩。
配置项 | 类型 | 默认值 | 说明 |
---|---|---|---|
localTempDir | string | /tmp | ToplingZipTable SST 创建过程中会用到临时文件,这里指定临时文件目录 |
enableStatistics | bool | true | 是否对 SST 的 Get 操作进行性能测量 |
keyPrefixLen | int | 0 | MyRocks 等 DB 系统使用固定长度的前缀(一般为 4)来区分不同的表或索引,不同的表或索引,其数据特征一般不同,应使用不同的压缩方案 |
checksumLevel | int | 0 | 0: 不启用 checksum 1: 只对元数据启用 checksum 2: 对每条数据单独 checksum 3: 对整个文件整体 checksum |
warmupLevel | enum | kIndex | 打开 SST 时预热文件(加载到内存) kNone: 不预热 kIndex: 预热 index kValue: 预热整个文件(包括 value 内容) |
debugLevel | int | 0 | 主要是为测试 |
sampleRatio | float | 0.03 | 采样率,因为 Value 的全局压缩需要采样 |
minPreadLen | int | 0 | 当 page fault 比较频繁时,使用 pread 性能会更好,因为需要的 IO 次数更少,并且避免了创建 PTE 的开销,该参数用来控制何时使用 pread < 0 : 不使用 pread == 0 : 总是使用 pread > 0 : 大于该值时使用 pread |
minPrefetchPages | int | 0 | 从 mmap 读取每条 value 时,如果 value 在文件中的尺寸较大(至少是跨了 Page 边界),一次性预读多少个 page,用来缓解随机访问时频繁的 page fault。0 表示禁用该功能,因为对 MADV_POPULATE_READ 的调用也有开销,在 page fault 很低时就没有必要 |
builderMinLevel | int | 0 | LSM 中以该层为界,更顶层的不使用 ToplingZipTable, 更底层(含)的才使用 ToplingZipTable。 这是为了在使用分布式 Compact 时,如果分布式 Compact 失败后回退到执行本地 Compact,就要消耗 DB 结点的计算资源,而 DB 结点的计算资源是紧缺的,所以此时我们希望使用创建开销更低的其它 TableFactory(例如 SingleFastTable), 该参数就是主要为了实现这个目的 |
indexType | string | Mixed_XL_ 256_32_FL |
默认的 NestLoudsTrie 类型,NestLoudsTrie 可以使用不同类型的 Rank-Select 实现,主要用于测试,正常使用默认值即可 |
indexNestLevel | int | 3 | NestLoudsTrie 索引的最大嵌套层数 |
indexNestScale | int | 8 | NestLoudsTrie 每嵌套每加深一层,深一层的尺寸就会减少,减少到最外层的多少分之一时,就停止嵌套
|
indexCacheRatio | float | 0 | NestLoudsTrie 底层 Select 操作可通过 Cache 加速,此为 Cache 比例,一般设为 0.01 以下,搜索可以加速约 10%, 更多的 Cache 加速效果不明显 |
indexTempLevel | int | 0 | 创建 NestLoudsTrie 时,使用临时文件可以减小内存占用,使用的临时文件越多,需要的内存就越少
|
indexMemAsResident | bool | false | 让 index 常驻内存 |
indexMemAsHugePage | bool | false | 让 index 使用 hugepage |
speedupNestTrieBuild | bool | true | NestLoudsTrie 创建时的优化参数,保持默认即可 |
optimizeCpuL3Cache | bool | true | Value 的全局压缩使用了多线程 Pipeline, 该压缩算法的内存字典较大,在字典中对内存的访问很随机,该选项尽可能让单一 SST 的数据在同一时刻进行压缩,以提升 CPU L3 Cache 的利用率,该参数保持默认即可 |
bytesPerBatch | int | 256K | 压缩 Value 时,Pipeline 中每个 Task 是一个 Batch,单个 Batch 中所有 value 的总尺寸 |
recordsPerBatch | int | 500 | 压缩 Value 时,单个 Batch 中所有 value 的数量上限 |
entropyAlgo | enum | kNoEntropy | 使用全局字典压缩 Value 之后再使用熵编码压缩一次,熵编码的压缩收益很小,但是解压/读取的开销很大,所以默认关闭,不建议开启。其它可选值:kHuffman, kFSE |
offsetArrayBlockUnits | int | 0 | 变长 Value 的定位通过 Offset 数组来实现,长度通过相邻 Offset 求差,该数组可以使用 PForDelta 压缩,该选项用来配置每个 PForDelta 压缩块的元素数量。0 表示不压缩;要压缩,首选 128, 还可设为 64, 不可设为其它值 |
minDictZipValueSize | int | 30 | 平均 Value 长度小于该值时,不压缩 |
keyRankCacheRatio | float | 0 | 用来加速 ApproximateOffsetOf, 设为 0 表示禁用,非零表示 Cache 从总体中的采样率 |
acceptCompressionRatio | float | 0.8 | 压缩后/压缩前 表示的 Value 的压缩率太差时,放弃压缩 |
nltAcceptCompressionRatio | float | 0.4 | NestLoudsTrie 的压缩率太差时,放弃使用该索引,改用其它类型的索引 |
softZipWorkingMemLimit hardZipWorkingMemLimit smallTaskMemory |
uint64 | 16G 32G 1.2G |
多个 Compact 并发执行时,每个都需要内存,所以要进行限制,预期内存用量超过软限制时,允许单个预期内存用量不超过 smallTaskMemory 的新任务执行,达到硬限制时,任何新任务都不得执行 |
fileWriterBufferSize | int | 128K | 写缓冲尺寸 |
fixedLenIndexCacheLeafSize | int | 512 | 对于 FixedLenKeyIndex, 配置其双数组查询缓存的叶节点尺寸,叶节点越大,缓存越小,保持默认即可 |
enableApproximateKeyAnchors | bool | true | 启用 ApproximateKeyAnchors, 主要用于 debug |
ToplingZipTable 是通过 SidePlugin 进行配置的,在(yaml)配置文件中,举例如下:
TableFactory:
zip:
class: ToplingZipTable
params:
localTempDir: "/dev/shm/tmp"
indexType: Mixed_XL_256_32_FL
indexNestLevel: 3
indexNestScale: 8
indexTempLevel: 0
indexCacheRatio: 0
warmupLevel: kIndex
compressGlobalDict: false
optimizeCpuL3Cache: true
enableEntropyStore: false
offsetArrayBlockUnits: 128
sampleRatio: 0.01
checksumLevel: 0
entropyAlgo: kNoEntropy
debugLevel: 0
softZipWorkingMemLimit: 16G
hardZipWorkingMemLimit: 32G
smallTaskMemory: 1G
minDictZipValueSize: 30
keyPrefixLen: 0
minPreadLen: 64
完整配置可参考 lcompact_enterprise.yaml
在 DispatcherTable 中,可以配置多个 ToplingZipTable,目的是采用不同的压缩选项,例如:
TableFactory:
lightZip:
class: ToplingZipTable
params:
localTempDir: "/dev/shm/tmp"
indexNestLevel: 3
indexNestScale: 8
minDictZipValueSize: 10M
将 minDictZipValueSize 设得很大,这样就不会对单条 value 平均长度小于 10M
的数据进行压缩,适合 LSM 中较上层的数据(例如 2,3 层),不压缩除了可以降低 Compact 中的 CPU 消耗,还可以大幅提升读性能,因为不压缩不仅可以免去解压操作,还可以使用 ZeroCopy,直接将 SST 存储 value 的 mmap 内存返回给用户代码。
lightZip 不压缩 value,但仍会压缩 index(使用 CO-Index)