大厂Data+Agent 秘籍:腾讯/阿里/字节解析如何提升数据分析智能。 了解详情
写点什么

ClickHouse 25.6 盛夏福利版:CoalescingMergeTree 表引擎

ClickHouse

  • 2025-07-29
    北京
  • 本文字数:3473 字

    阅读完需:约 11 分钟

大小:1.60M时长:09:20
ClickHouse 25.6 盛夏福利版:CoalescingMergeTree 表引擎

我们在 ClickHouse 25.6 的版本发布文章中已经介绍了很多功能,但实际上我们还有一个非常酷的新功能,保证大家会被“冰冻”的。😎


所以这就是你的夏日加餐博客,正好适合你躺在沙滩上时读一读:这次我们要专门介绍 CoalescingMergeTree —— 一个全新的表引擎,专为整合稀疏更新设计,可以在不损失数据完整性的前提下,帮你有效减少行数。


如果你是那种涂防晒霜的间隙也不忘查看 ClickHouse 更新的人,这篇文章正合你胃口。🏝️


让我们一探究竟。

CoalescingMergeTree 表引擎


贡献者:Konstantin Vedernikov


MergeTree 表引擎家族难得迎来新成员,因此这次的全新引擎 CoalescingMergeTree,值得我们用一整篇文章来介绍。


CoalescingMergeTree 能够在合并过程中,逐步将稀疏的记录合并,非常适合以下场景:


  • 你希望高效地保留每个实体的最完整版本。

  • 你可以接受在数据合并时,最终在磁盘上实现整合。

  • 你希望避免像 ReplacingMergeTree 那样整行覆盖,只想填补缺失的字段。


一个典型的应用场景:IoT 设备的状态或配置快照。比如,车队的可观测性,就像 Tesla 那样[https://clickhouse.com/blog/how-tesla-built-quadrillion-scale-observability-platform-on-clickhouse]。


在现代的联网车辆,尤其是电动车中,遥测数据的更新通常来自不同的子系统:

  • 电池模块汇报电量

  • GPS 模块发送位置信息

  • 软件更新模块上报固件版本

  • 传感器定期更新温度和速度


我们希望通过 CoalescingMergeTree,将这些增量的、稀疏的更新整合成每辆车的完整视图。


表定义



示例数据插入



为什么不直接用 UPDATE?


在许多数据库中,处理类似的状态变更通常会通过更新已有的行来实现,比如使用 UPDATE 指令来刷新最新的温度或固件版本。ClickHouse 当然也支持快速、频繁的单行 UPDATE。你可以在我们最近的 Open House 2025 用户大会上看到相关的功能演示[https://clickhouse.com/openhouse]。对于某些工作负载,这种方法确实很适用。


但在高吞吐量的 IoT 场景,这种做法就显得低效了:UPDATE 需要先找到已有的那一行,然后重写,过程中往往还会锁定或改写比必要更多的数据。


ClickHouse 更提倡一种简单的追加式模型:只要有新字段到达,直接插入即可。CoalescingMergeTree 则在此基础上再进一步,通过后台合并机制,自动把这些稀疏的插入记录整合成完整、紧凑的记录(后文我们会详细介绍)。这种方式尤其适合高写入量、高基数,且更新频繁但每次只改部分字段的场景。


ClickHouse 对插入型工作负载做了深度优化:插入操作是完全隔离的,支持并行写入,彼此不会产生干扰,且可以全速写入磁盘,因为 ClickHouse 不存在需要锁定或更新的全局结构(比如全局 B++ 索引)。而记录合并等额外的计算工作,都是通过后台合并任务来异步完成,从而保证插入操作始终轻量高效。

正是这种架构,使得 ClickHouse 在生产环境中能够实现超高的写入吞吐量。在某些部署场景下,ClickHouse 的稳定写入速度可超过每秒 10 亿行,同时保持内存和 CPU 使用的稳定。


要点:万亿级行数的挑战


在高吞吐量的 IoT 系统中,成千上万甚至上百万台设备持续不断地发送数据。每次更新往往只涉及一两个字段,结果就是表中充斥着大量稀疏且冗余的行。


为了还原每个设备的最新完整状态,你需要从每列中提取最新的非 null 值。ClickHouse 即使使用普通的 MergeTree 引擎,也可以通过 argMax() 聚合函数来实现这一点。


下面是 electric_vehicle_state 表在经过几次稀疏更新后的样子(假设还没有发生任何数据部分的合并,稍后会解释原因)。为了简洁,last_update 的时间戳被简化了:




接着,这是使用 argMax() 查询每个设备最新状态的方法:



argMax 在这里非常适用,因为它可以保留每列的最新非 null 值。

具体来说,argMax(x, t) 会返回时间戳 t 最大且 x 不为 null 的那一行的 x 值。如果存在更晚的时间戳,但对应的 x 是 null,这些行会被跳过。


但如果完全依赖常规的 MergeTree 和 argMax(),就意味着:

  • 每次查询都要全表扫描

  • 每次都需要实时计算聚合


当表的规模达到数十亿、甚至万亿行时,这种方式的效率就会变得非常低下。

CoalescingMergeTree 如何解决这个问题


使用 CoalescingMergeTree,ClickHouse 可以在物理存储层,将具有相同排序键(如 VIN)的一组行合并。在后台的部分合并过程中,ClickHouse 会对每个排序键,仅保留每列最新的非 null 值,实现了磁盘上的预聚合:



上图展示了不同子系统(如电池、GPS、传感器)产生的稀疏更新,如何通过 CoalescingMergeTree 逐步合并为一个完整的设备状态。每次更新只改动部分字段,ClickHouse 会在后台合并时,自动将排序键相同(例如 vin)的行合并,形成最新的完整设备视图。


图中展示了 7 个数据部分[https://clickhouse.com/docs/parts]:最初的插入数据(①–④)、中间合并形成的部分(⑤、⑥),以及最终的活跃部分 ⑦。合并完成后,①–⑥ 会变为非活跃数据并被自动清理。此后,查询只需在这个单一、紧凑的数据部分 ⑦ 上执行,效率大大提升。


需要注意的是,这里的“最新”并非依据时间戳列判断,而是基于行的物理插入顺序。合并时,CoalescingMergeTree 会使用各数据部分在磁盘上的写入顺序。对于每列,ClickHouse 保留的是合并过程中,排序键下,最近写入的非 null 值。

比如图中,数据部分 ① 到 ⑦ 按写入顺序排列,① 最早,⑦ 最新。


这种方式极大地降低了:

  • 每个设备对应的行数

  • 查询时需要扫描的数据量


读取最新状态:argMax 与 FINAL


在 IoT 这样的高写入场景中,后台合并通常跟不上插入的速度(合并在后台持续运行,但写入总是更快,就像有个合并滞后的窗口)。


即便如此,为了保证查询准确性,我们仍会使用 GROUP BY 和 argMax(),但由于后台合并已经完成了大部分整合,实际需要处理的行数大大减少。


(前文的图示中为了简洁省略了 last_update 列。它并不影响 CoalescingMergeTree 的合并逻辑,后台合并会自动保留每列的最新非 null 值。但如果你在查询时使用 argMax(),就需要依靠 last_update 这样的时间戳来判断“最新”是哪一行。)



如果所有数据部分已经合并完成且没有新数据插入,直接 SELECT * 查询就可以,不需要再加 GROUP BY。



在持续更新的场景下,也可以通过查询时加上 FINAL 修饰符,临时应用 CoalescingMergeTree 的合并逻辑(上文图示已讲解),这样就不用在查询时再做聚合。FINAL 不会将合并结果写回磁盘,而是针对当前查询,在内存中对相关数据做一次合并,生成完整的记录,避免了使用 GROUP BY 或 argMax():



注意,使用 FINAL 后,last_update 字段就不再是必须的,因为 FINAL 在查询时依据插入顺序来判断最新值,不依赖时间戳。

但如果查询不用 FINAL,而是通过 argMax() 来聚合,就仍然需要时间戳列如 last_update。因为当数据部分尚未合并时,查询引擎无法直接知道写入的时间或行的物理顺序,必须借助时间戳来判断。


推荐的存储模式:原始表 + 整合表


我们推荐搭配使用 CoalescingMergeTree 和常规的 MergeTree 表,通常可以通过物化视图来实现[https://clickhouse.com/docs/materialized-views]

  • MergeTree 表用来存储原始事件流,完整保留每辆车或设备的所有更新记录。

  • CoalescingMergeTree 表则用于存储整合后的视图,例如每辆车的最新状态,适合用于仪表盘、定期报表或分析型查询。


这种双表模式,既保证了所有原始数据的留存,又能通过物理行整合,提升查询和存储的效率。更重要的是,如果排序键不能唯一标识每个事件,原始表仍然保留了完整数据,方便日后恢复或重算。


更多应用场景


除了 IoT 快照,任何存在稀疏、追加式更新,逐渐丰富记录的场景,CoalescingMergeTree 都很合适,比如:


  • 用户画像补全:邮箱、电话、位置等信息随着用户交互逐渐补全。

  • 安全审计日志:事件逐步添加更多上下文,如操作者身份、受影响系统。

  • ETL 流程的迟到维度:后续补充步骤为缺失字段赋值。

  • 患者健康档案:实验室结果、医生笔记和生命体征等来自不同系统,逐步补充。

  • 广告或营销活动跟踪:展示和点击等信息从不同系统在不同时间汇集。

  • 客户支持工单:随着收集更多信息(如严重程度、解决方案),工单持续完善。


这些场景下,CoalescingMergeTree 能在保证数据完整性的同时,降低存储成本,提升查询性能。

就这样,去享受你的夏日时光吧


你的 ClickHouse 知识已经更新,是时候给自己充充电了。


等你回来时,我们还在这儿。🏖️🍹


夏天快乐,查询顺利!


征稿启示


面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出 &图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com。




2025-07-29 14:0510

评论

发布
暂无评论

VictoriaMetrics 中文教程(10)集群版介绍

巴辉特

Victoriametrics VictoriaMetrics教程

如何使用OPA(开放策略代理)管理您的API策略

Gingxing

kong API网关 Kong 网关 消息网关 Kong Gateway

F5搭载NVIDIA BlueField-3 DPU赋能加速 AI 应用交付

科技热闻

BY林子的“软件质量与测试”赋能体系

BY林子

质量管理 软件测试 软件质量 质量赋能

试验协同管理平台(源码+文档+部署+讲解)

深圳亥时科技

人工智能 | 语音识别模型

测吧(北京)科技有限公司

测试

日喀则等保测评机构有哪些?电话多少?

行云管家

网络安全 等保 日喀则

实时监控商品信息api接口,加速迭代优化:助力商家产品持续精进之路

代码忍者

API 接口 pinduoduo API

智慧环保系统(源码+文档+部署+讲解)

深圳亥时科技

数字身份发展趋势前瞻:无密码认证

芯盾时代

数字身份 身份安全 iam 统一身份认证

又是一年双11,火山引擎数据飞轮助力品牌激活“老客”、拉来“新客”

字节跳动数据平台

AI赋能,中国企业管理软件崛起正当时

人称T客

面向 Data+AI 的统一数据目录探索 | Data Infra NO.22 回顾(含资料发布)

Databend

CST软件发展历程—完备的技术

思茂信息

求解器 cst cst仿真软件

深度解读RDS for MySQL 审计日志功能和原理

华为云开发者联盟

MySQL 数据库 华为云RDS for MySQL 审计日志

《使用Gin框架构建分布式应用》阅读笔记:p234-p250

codists

golang gin 编程人 codists

C#使用Socket实现分布式事件总线,不依赖第三方MQ

沙漠尽头的狼

《智能文档处理“百宝箱”:数字化时代文档处理的必备利器》

袁袁袁袁满

人工智能 AI 图像识别 大模型

携手火山引擎,易点天下AI布局加速拓展

新消费日报

审计考核系统(源码+文档+部署+讲解)

深圳亥时科技

时尚零售企业商品计划管理的数字化之旅

第七在线

ClickHouse 25.6 盛夏福利版:CoalescingMergeTree 表引擎_数据集成_InfoQ精选文章