TiDB LSM合并使用什么算法

合并过程的算法是怎样的?

LSM-Tree(日志结构合并树)的核心是 “写时追加、后台合并”:数据先写入内存(MemTable),刷盘后形成 SST 文件,后台通过 Compaction 将小文件合并成大文件,同时清理删除 / 过期数据。

lsm-tree是有序的kv,合并很简单,把没用的key删了,把有用的key排序

TiDB LSM 合并核心是后台 Compaction:合并 SST 文件,清理无效数据,保持 KV 有序。

Compaction 策略:常见 Leveled Compaction(按层级合并)和 Size-Tiered Compaction(按大小分组合并),平衡读写性能与合并开销。

我感觉就是level0的immutable mem镜像,接下来就是分段排序合并,逐步进入freeze的最后阶段sst

TiDB是用的哪种合并策略?

TiDB的核心合并策略是基于Percolator优化的两阶段提交

  • 配置参数参数
    TiKV 内可使用compaction-style参数修改每个CF的compaction 算法:
    可选值:“level”,“universal”,“fifo”
    默认值:“level”

  • 算法介绍:
    level:RocksDB的leveled compaction中 level 0包含有多个sorted-run,有多个sst文件,之间存在数据重叠,在compaction时将所有L0文件合并到L1层。对于L1-Lmax 层,每一层都是一个有序的Rorted-Run,包含有多个sst file。在进行读取时首先使用二分查找可能包含数据的文件,然后在文件内使用二分查找需要的数据。
    Universal(tiered):Tiered 方式同样每层可以包含多个Sorted-Run ,Ln 层所有的数据向下合并到Ln+1层新的Sorted-Run,不需要读取Ln+1层原有的数据。Tiered方式能够最大的减少写放大,提升写入性能。
    fifo:只有1层,写放大最小,每次compaction删除最老的文件,适合于带时间序列的数据。

  • 详见:

1 个赞

lsm-tree是有序的kv,合并很简单,把没用的key删了,把有用的key排序

TiDB 的存储引擎 TiKV基于 LSM-Tree设计,其它的LSM 合并过程核心采用 分层级的归并排序 ,并结合 TiKV 自身的架构特点做了针对性优化

OcenaBase也是LSM结构,它是完全自己实现还是也用的RocksDB?

看了这篇博客,里面写RocksDB的leveled compaction中 level 0包含有多个sorted-run,有多个sst文件,之间存在数据重叠,在compaction时将所有L0文件合并到L1层。
有个疑问:这里的sorted-run是指把L0层的转储文件又重新生成了个排序文件的意思?

  • Leveled-N

     和上面Classic Leveled 类似,不过每层可以有N个Rorted-Run,每层的数据不是完全有序的
    

这里的Rorted-Run是笔误还是就有这么个东西,看的太吃力了,不是很明白

网上搜了搜,应该是自己实现的。

1. Size-Tiered Compaction Strategy(STCS)( 上文中的Universal

STCS(大小分层合并策略,亦称 Tiered Compaction)以优化写入性能为主要目标

工作原理:

  • 初始阶段 :MemTable 刷盘后,生成一系列大小相近的小 SSTable 文件(如 64MB)。
  • 触发合并 :当同层文件数量达到阈值(例如 4 个)时,触发合并。
  • 合并过程 :该层所有文件被读入内存,进行多路归并排序,合并成一个新的、更大的 SSTable 文件。
  • 层级晋升 :新文件晋升至下一层。当该层文件再次达到阈值时,继续向上合并,文件体积逐层倍增。

核心缺点:读放大高。
由于同层 SSTable 键范围重叠,点查询最坏需检查层内所有文件;范围查询则需合并多个文件的数据,开销更大。


2. Leveled Compaction Strategy(LCS)

LCS(分级合并策略)专注于优化读取性能和空间利用率 ,是 LevelDB/RocksDB 的默认策略。

数据组织:

  • L0 层 :接收 MemTable 刷盘文件,允许键范围重叠。
  • L1 及以上层 :每层内部 SSTable 的键范围严格不重叠 ,任一键最多只存在于该层的一个文件中。

优点:读取性能优秀。
点查询只需检查 L0 所有文件,并在 L1+ 的每层中快速定位唯一 可能的目标文件,读放大低。

缺点:写放大高。
数据从 L0 迁移至最高层的过程中,会在各级合并中被反复重写。


3. RocksDB 的混合策略:L0 层 Tiered,L1+ 层 Leveled

RocksDB 默认策略融合了 STCS 与 LCS 的优点 ,是一种经典且成功的混合方案。

  • L0 层采用 Tiered 思想 :允许键范围重叠,作为写入缓冲。当文件数达到阈值时,才触发向 L1 的合并,能有效平滑写入峰值,避免写阻塞。
  • L1 及以上层采用 Leveled 思想 :严格保持层内 SSTable 键范围不重叠,确保绝大多数数据的查询具有低读放大和高效率。

混合设计优势:

  • 高写入吞吐量 :L0 层缓冲写入压力。
  • 优秀读取性能 :L1+ 层结构保障查询效率。
  • 可控空间放大 :继承了 LCS 在空间管理上的优势。

当 MemTable(内存表)被刷盘(Flush)时,或者在 Compaction 过程中,系统会先将数据分割成多个小的、局部有序的块(Block)。这些块被称为 Sorted Runs。
为了快速定位数据,SSTable 会在这些 Sorted Runs 的基础上构建索引结构。
最终,所有的 Sorted Runs 和索引信息被打包进一个不可变的文件中,这就是 SSTable。

lsm-tree算法,现在很多数据库使用此算法,比如:OCEANBASE,特点是写快,但存在多个版本后读性能变差,合并后改善

多谢,我再琢磨琢磨这里的细节!

是的,clickhouse也是用这个算法,对写入友好,需要做异步合并。