You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ClickHouse数据更新去重选型:ReplacingMergeTree vs CollapsingMergeTree?

ClickHouse引擎选型:ReplacingMergeTree vs CollapsingMergeTree 适配美容沙龙会话记录表场景

你的场景核心需求

  • 表records存储美容沙龙会话数据,包含预约、到店状态、付费情况等字段
  • 每15分钟批量更新:新增预约记录 + 修改已有记录的状态、付费、备注、schedule_id等信息
  • 数据需实时同步到Superset仪表板,确保展示的是最新状态
  • 当前表约3万行,未来会有持续增长的更新量

两种引擎的优劣势适配分析

CollapsingMergeTree

优势:通过sign标记(+1新增/更新,-1作废旧记录),合并后能精准保留最新数据,理论上数据准确性最高。
致命痛点:完全不匹配你的更新流程。你从API获取最新值,旧值仅存储在库中,每次更新都要先查询旧记录,再插入一条标记为-1的作废记录,最后插入+1的新记录。这个流程不仅增加了额外的查询和写入步骤,还容易出现竞态问题(比如查询旧记录后,旧记录又被其他更新修改),随着数据量增长,维护成本会越来越高。

ReplacingMergeTree

特性:按ORDER BY指定的键自动保留最新版本的记录,但合并操作是异步触发的,默认情况下会短时间内存在同键的多条记录。
适配你的场景的优化方案:

  1. 新增update_date字段作为版本标记,每次更新时写入当前时间
  2. 建表时指定ReplacingMergeTree(update_date),让引擎按update_date保留最新的记录
  3. Superset查询时使用FINAL修饰符,强制触发合并,直接获取去重后的最新数据

这个方案的好处:

  • 写入逻辑极简:直接插入新记录即可,不需要处理任何标记,完全适配你从API拿数据直接更新的流程
  • 数据实时性有保障:FINAL查询会确保拿到最新的合并后数据,满足Superset仪表板的实时需求
  • 性能可控:当前3万行数据下,FINAL查询的开销可以忽略;即使未来数据增长到几十万行,只要查询不是极端高频,依然能稳定运行

最终选型结论

优先选择ReplacingMergeTree,它能以最简单的写入逻辑满足你的实时更新和数据展示需求,避免CollapsingMergeTree带来的额外开发和维护成本。

优化后的建表语句

CREATE TABLE do_you_database.records
(
    record_id UInt32,
    plan_id Nullable(UInt64),
    schedule_id Nullable(UInt64),
    client_id UInt32,
    visit_id UInt32,
    visit_date Nullable(DateTime),
    status Int8,
    visit_duration UInt32,
    paid bool,
    comment Nullable(String),
    source Nullable(String),
    create_date DateTime,
    update_date DateTime, -- 新增:每次更新时写入当前时间,作为版本标记
    user_id UInt32
)
ENGINE = ReplacingMergeTree(update_date) -- 指定按update_date保留最新版本
ORDER BY (record_id); -- 按record_id分组,确保同一条记录的版本会被合并

Superset查询示例

SELECT * FROM do_you_database.records FINAL WHERE -- 你的查询条件;

内容的提问来源于stack exchange,提问作者John Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:02:16