跳到主要内容
跳到主要内容

分区合并

ClickHouse 中的分区合并是什么?


ClickHouse 快速 不仅在查询时表现快速,在插入时也表现出色,这得益于其 存储层,该层的操作类似于 LSM 树

① 插入(到来自 MergeTree 引擎 的表中)会创建排序的、不可变的 数据部分

② 所有数据处理都卸载到 后台分区合并 中。

这使得数据写入变得轻量且 高效

为了控制每个表的部分数量并实现上述②,ClickHouse 在后台不断将较小的部分合并成较大的部分(按分区),直到它们的压缩大小达到大约 ~150 GB

下图概述了这个后台合并过程:


每进行一次额外的合并,部分的 merge level 就会增加一。0级别表示该部分是新的,尚未被合并。合并成较大部分的部分会被标记为 非活动,并在 可配置的 时间后(默认8分钟)最终被删除。随着时间的推移,这会创建一个 树形 的合并部分。因此称之为 merge tree 表。

监控合并

什么是表部分 的示例中,我们 显示了 ClickHouse 如何在 parts 系统表中跟踪所有表部分。我们使用以下查询来检索示例表每个活动部分的合并级别和存储的行数:

先前文档中的查询结果显示示例表有四个活动部分,每个部分均来自最初插入部分的单次合并:

现在运行 查询 后显示这四个部分已经合并成一个最终部分(只要表中没有进一步的插入):

在 ClickHouse 24.10 中,内置的 监控仪表盘 添加了新的 合并仪表盘。通过 /merges HTTP 处理程序在 OSS 和 Cloud 中都可用,我们可以用它来可视化示例表的所有部分合并:


上述记录的仪表盘捕捉了整个过程,从初始数据插入到最终合并成一个部分:

① 活动部分的数量。

② 部分合并,以框的形式可视化(大小反映部分的大小)。

写放大

并发合并

单个 ClickHouse 服务器使用多个后台 合并线程 来执行并发分区合并:


每个合并线程执行一个循环:

① 决定下一个要合并的部分,并将这些部分加载到内存中。

② 在内存中将部分合并成一个更大的部分。

③ 将合并后的部分写入磁盘。

回到 ①

请注意,增加 CPU 核心数和 RAM 大小可以提高后台合并的吞吐量。

内存优化合并

ClickHouse 不一定会一次将所有要合并的部分加载到内存中,如 之前的示例 所示。根据多个 因素,并为了减少内存消耗(牺牲合并速度),所谓的 垂直合并 按块的块加载和合并部分,而不是一次性合并。

合并机制

下图说明了 ClickHouse 中单个后台 合并线程 如何合并部分(默认情况下,不进行 垂直合并):


部分合并分几个步骤进行:

① 解压缩和加载:要合并的部分的 压缩二进制列文件 被解压缩并加载到内存中。

② 合并:数据被合并成更大的列文件。

③ 索引:为合并的列文件生成新的 稀疏主索引

④ 压缩与存储:新列文件和索引被 压缩 并存储在一个新的 目录 中,代表合并的数据部分。

部分中的额外 元数据,如二级数据跳过索引、列统计信息、校验和和最小最大索引,也基于合并的列文件重新创建。为了简化,我们省略了这些细节。

步骤②的机制取决于使用的特定 MergeTree 引擎,因为不同的引擎以不同的方式处理合并。例如,行可以被聚合或替换,如果过时。如前所述,这种方法 将所有数据处理卸载到后台合并中,通过保持写操作轻量且高效,实现 超快速的插入

接下来,我们将简要概述 MergeTree 家族中特定引擎的合并机制。

标准合并

下图说明了标准 MergeTree 表中部分是如何合并的:


上图中的 DDL 语句创建了一个 MergeTree 表,排序键为 (town, street),这意味着磁盘上的数据是按这些列排序的,并相应生成稀疏主索引。

① 解压的、预排序的表列被 ② 合并,同时保持表的全局排序顺序,该顺序由表的排序键定义, ③ 生成新的稀疏主索引, ④ 合并后的列文件和索引被压缩并存储为新的数据部分在磁盘上。

替换合并

ReplacingMergeTree 表中的部分合并的工作方式类似于 标准合并,但仅保留每行的最新版本,丢弃旧版本:


上图中的 DDL 语句创建了一个排序键为 (town, street, id)ReplacingMergeTree 表,这意味着磁盘上的数据是按这些列排序的,并相应生成稀疏主索引。

② 合并的过程与标准 MergeTree 表类似,合并解压的、预排序的列,同时保持全局排序顺序。

但是,ReplacingMergeTree 会删除具有相同排序键的重复行,仅保留根据其包含部分的创建时间戳确定的最新行。


求和合并

SummingMergeTree 表中的部分合并时,数值数据会自动汇总:


上图中的 DDL 语句定义了一个以 town 为排序键的 SummingMergeTree 表,这意味着磁盘上的数据是按此列排序的,并相应生成稀疏主索引。

在 ② 合并步骤中,ClickHouse 用一行替换所有具有相同排序键的行,同时对数值列的值进行求和。

聚合合并

上面的 SummingMergeTree 表例是 AggregatingMergeTree 表的一个特化变体,允许在部分合并过程中应用任何 90+ 聚合函数,从而实现 自动增量数据转换


上图中的 DDL 语句创建了一个以 town 为排序键的 AggregatingMergeTree 表,确保磁盘上的数据是按此列排序的,并相应生成稀疏主索引。

在 ② 合并过程中,ClickHouse 用一行替换所有具有相同排序键的行,存储 部分聚合状态(例如,avg()sumcount)。这些状态确保通过增量后台合并获得准确的结果。