讲讲 Doris的“写放大(Write Amplification)”?如何通参数过调优?
在 Apache Doris 中,写放大(Write Amplification, WA)是一个非常核心的性能与存储概念。理解并优化写放大,对于提升 Doris 的写入吞吐、降低磁盘 I/O 压力、延长 SSD 寿命以及稳定查询延迟至关重要。
一、 什么是 Doris 的“写放大”?
简单来说,写放大是指:实际写入物理磁盘的数据量大于用户逻辑写入的数据量。
写放大倍数 = 实际写入磁盘的数据量 / 用户发送的原始数据量
为什么 Doris 会存在写放大?
Doris 的底层存储引擎采用了类似 LSM-Tree(Log-Structured Merge-tree) 的架构。这种架构为了获得极高的写入性能,采用了“先追加写,后合并(Compaction)”的策略:
- MemTable 刷盘(Flush):用户写入的数据先缓存在内存中,达到阈值后溢写到磁盘,形成一个个小的 Segment 文件(Rowset)。
- 压实/合并(Compaction):为了避免小文件过多影响查询性能,Doris 会在后台不断地将多个小的 Segment 文件合并成大文件,并在此过程中进行去重(Unique Key)或聚合(Aggregate Key)。
- Cumulative Compaction (CC):把新产生的小 Rowset 合并成较大的 Rowset。
- Base Compaction (BC):把 CC 合并后的较大 Rowset 与历史最底层的 Base Rowset 进行合并。
写放大的主要源头就是 Compaction。一条数据被写入后,可能会在 CC 和 BC 的过程中被反复读取并重新写入磁盘多次。如果一条数据被重写了 10 次,写放大倍数就是 10。
二、 写放大的危害
- 磁盘 I/O 暴涨:频繁的磁盘读写导致 I/O 达到瓶颈(I/O Util 100%),进而导致查询变慢、导入变慢。
- CPU 消耗过大:Compaction 合并数据需要进行解压、排序、去重、压缩,消耗大量 CPU。
- SSD 寿命缩短:高频的写放大会加速 SSD 闪存颗粒的磨损。
三、 如何通过参数调优控制写放大?
优化写放大的核心思路是:减少小文件的产生(源头控制) + 优化后台合并的频率和激进程度(过程控制) + 合理选择数据模型(架构控制)。
以下是具体的调优参数和策略:
1. 源头控制:减少小文件导入(最有效)
如果导入频率极高,每次导入数据量极小(如单条插入),会产生海量小文件,导致极其恐怖的写放大。
开启 Group Commit(组提交)
Doris 2.0+ 引入了 Group Commit,将高频的小并发写入在 BE 端内存中攒批,然后一次性写入。- 作用:大幅减少 Rowset 数量,从源头上消灭写放大。
- 设置方式(在 Session 级别或 Global 级别开启):sql
SET enable_group_commit = true; -- 组提交延迟时间(默认10ms,可适当放大,如 100~500ms 以获得更大吞吐) -- 在 fe.conf 中配置或通过 session 变量设置
增大导入攒批大小
如果是 Stream Load 或 Routine Load,尽量调大单次导入的数据量或时间间隔(例如从 5秒一次改为 30秒/1分钟一次)。
2. Compaction 参数调优(BE 配置)
通过调整 be.conf 中的参数,可以控制 Compaction 的触发时机和合并力度。
A. 调整 Cumulative Compaction (CC) 晋升阈值
CC 的数据达到一定大小后,会“晋升”等待 Base Compaction。如果这个阈值设得太小,数据会过早进入 BC,而 BC 的写放大代价极大。
compaction_promotion_size_mbytes- 默认值:1024 (1GB)
- 调优建议:如果磁盘空间充足、I/O 压力大,可以适当调大(如
2048或5120),让数据在 CC 阶段多呆一会儿,减少进入 BC 的频率。
compaction_promotion_ratio- 默认值:0.05 (5%)
- 说明:当 Rowset 尺寸达到 Base Rowset 的这个比例时,晋升。可以适当调大。
B. 控制 Compaction 并发与资源限制
限制同时进行的 Compaction 线程数,防止其抢占过多的磁盘 I/O。
compaction_task_num_per_disk- 说明:每个磁盘用于 compaction 的线程数。
- 调优:如果 SSD I/O 跑满,可以将此值调小(例如从默认的 2 或 4 降到
1或2)。
max_compaction_concurrency- 说明:BE 节点总的 compaction 并发数限制。默认一般为 CPU 核数的一半,I/O 压力大时可限制其最大值(如
8或16)。
- 说明:BE 节点总的 compaction 并发数限制。默认一般为 CPU 核数的一半,I/O 压力大时可限制其最大值(如
C. 调整 Size By Ratio 策略参数
Doris 的 CC 采用 Size By Ratio 策略(按比例合并)。
cumulative_compaction_min_multi_threshold- 默认值:5
- 说明:最少有多少个 Rowset 才触发 CC。
- 调优:可以适当放大到
10甚至20。这样可以一次性合并更多的小文件,减少中间重复合并的次数(即“用空间换 I/O”,短期内文件数较多,但写放大降低)。
cumulative_compaction_max_multi_threshold- 默认值:10
- 说明:一次 CC 最多合并多少个 Rowset。可以适当调大(如
30)。
3. 数据模型选择(架构设计)
不同的数据模型,写放大行为完全不同:
- Duplicate Key(明细模型):写放大最小。因为不需要去重或聚合,Compaction 只是简单的多路归并排序并写回。
- Aggregate Key(聚合模型):写放大会合并相同 Key 的 value。
- Unique Key (Merge-on-Read, MoR):写放大较小,因为只在查询时合并。
- Unique Key (Merge-on-Write, MoW):写放大最大。因为在写入时,需要通过主键索引找到旧数据,并在原来的 Rowset 中写入 Delete Bitmap(标记删除)。虽然 MoW 查询极快,但高频写入下的写放大非常严重。
- 优化建议:如果 Unique Key 模型的表写入极为频繁,且对查询延迟没有极致要求(如秒级响应即可),可以考虑切换为 MoR (Merge-on-Read) 模式。
4. 磁盘配置(硬件协同)
- 冷热数据分层:
将热数据(刚写入、需要频繁 Compaction)放在 SSD 上,将冷数据(不再写入)迁移到 HDD 或对象存储。Doris 支持冷热分层(Storage Policy),这能有效避免 HDD 被 Compaction 拖垮。
四、 调优效果评估
如何判断调优是否起作用?可以通过以下指标观察:
- Compaction Score (合并得分):
通过 Doris FE 的 Web 界面或 Metrics 监控tablet_cumulative_max_compaction_score。如果 score 长期处于几百甚至上千,说明 Compaction 严重积压。 - 磁盘写入 I/O 流量:
对比系统 I/O 写入流量与 Doris 导入吞吐量。若导入 1MB 数据,系统写入达到 20MB/s,说明写放大严重。 - BE 线程状态:
观察show backends中的CompactionStatus,或者通过 Grafana 监控 Doris 提供的 Compaction 相关 Metrics(如compaction_bytes_written)。
总结口诀:
大批导入防小件(Group Commit),
延迟晋升护大盘(调大 promotion_size),
线程设限控并发(限制 task_num),
模型选对事半功(明细极佳,独钥慎选 MoW)。