ReplacingMergeTree 去重与 FINAL
ReplacingMergeTree 在后台合并(merge)时按排序键去重,保留版本列取值较大的那一行;去重发生在合并阶段而不是写入阶段,所以合并完成前同一个键可能有多行可见。查询加 FINAL 可以强制返回去重后的最新行,代价是牺牲并行度、随数据量上升明显变慢。
基本信息
| 引擎 | ReplacingMergeTree |
|---|---|
| 去重键 | ORDER BY 指定的列 |
| 版本列 | 可选,决定保留哪一行 |
| FINAL | 查询期强制去重 |
| 合并时机 | 后台异步,时间不可控 |
典型使用场景
- 维表按主键保留最新版本:门店、商品属性变更只需写入新版本行
- 明细去重:同一订单重复投递时按排序键加版本列收敛为一条
- 总量类统计:不依赖 FINAL,或按版本过滤后再聚合,避免查询期开销
- 高并发明细查询:改为查询前先去重,或直接使用已去重的聚合表
- 调优排查:确认 OPTIMIZE 是否在运行、单分区是否过大导致合并追不上写入速度
按版本取最新
按版本取最新
-- 不依赖 FINAL 的等价写法:按排序键取版本最大的一行
SELECT store_id, store_name
FROM (
SELECT store_id, store_name,
row_number() OVER (PARTITION BY store_id ORDER BY version DESC) AS rn
FROM dw.dim_store
)
WHERE rn = 1;
-- 主动触发合并(大表开销高,宜按分区执行)
OPTIMIZE TABLE dw.dim_store FINAL;去重手段对比
| 手段 | 代价 | 适用 |
|---|---|---|
| 依赖后台合并 | 自动但时机不可控 | 最终一致可接受的统计场景 |
| 查询加 FINAL | 查询开销随数据量上升 | 小表或偶发的精确查询 |
| 按版本取最新 | 需要排序聚合 | 明细类精确查询 |
| 入仓前去重 | 写入端多一步处理 | 高频读取的维表 |
ReplacingMergeTree 的语义是最终一致:合并时间不由使用者决定,因此对准确性要求高的查询不能只依赖后台合并,应显式去重。
较新版本的 ReplacingMergeTree 支持额外的删除标记参数(is_deleted),可用于逻辑删除;升级或跨集群迁移前先核对目标版本的参数支持情况,避免建表语句不兼容。