ReplacingMergeTree
该引擎与 MergeTree 的不同之处在于它删除具有相同 sorting key 值的重复条目(ORDER BY
表部分,而不是 PRIMARY KEY
)。
数据去重仅在合并时发生。合并在背景中以未知的时间进行,因此无法进行计划。一些数据可能会保持未处理状态。尽管可以使用 OPTIMIZE
查询运行非计划性合并,但不要依赖它,因为 OPTIMIZE
查询将读取和写入大量数据。
因此,ReplacingMergeTree
适合在后台清除重复数据以节省空间,但不能保证不存在重复项。
有关 ReplacingMergeTree 的详细指南,包括最佳实践和如何优化性能,可以在 这里 找到。
创建表
有关请求参数的描述,请参阅 statement description。
行的唯一性由 ORDER BY
表部分确定,而不是由 PRIMARY KEY
。
ReplacingMergeTree 参数
ver
ver
— 版本号列。类型为 UInt*
、Date
、DateTime
或 DateTime64
。可选参数。
在合并时,ReplacingMergeTree
会从所有具有相同排序键的行中仅保留一个:
- 如果未设置
ver
,则选择中的最后一行。选择是一组参与合并的一组分区中的行。最近创建的分区(最后插入的)将在选择中排在最后。因此,在去重之后,对于每个唯一排序键,来自最近插入的最后一行将保留下来。 - 如果指定了
ver
,则保留最大版本的行。如果ver
对于几行相同,则将对它们应用“如果未指定ver
”的规则,即保留最近插入的行。
示例:
is_deleted
is_deleted
— 在合并过程中用于判断该行数据是否表示状态或需被删除的列名称;1
为“已删除”行,0
为“状态”行。
列数据类型 — UInt8
。
仅在使用 ver
时,可以启用 is_deleted
。
无论对数据执行何种操作,版本应增加。如果两个插入的行具有相同的版本号,则保留最后插入的行。
默认情况下,即使该行是删除行,ClickHouse 也会保留某个键的最后一行。这是为了确保可以安全地插入任何未来具有较低版本的行,并且删除行仍会被应用。
要永久删除这些删除行,请启用表设置 allow_experimental_replacing_merge_with_cleanup
,并执行以下任一操作:
-
设置表设置
enable_replacing_merge_with_cleanup_for_min_age_to_force_merge
、min_age_to_force_merge_on_partition_only
和min_age_to_force_merge_seconds
。如果分区中的所有分区片段均超过min_age_to_force_merge_seconds
,ClickHouse 将将它们全部合并为一个单一的分区并移除任何删除行。 -
手动运行
OPTIMIZE TABLE table [PARTITION partition | PARTITION ID 'partition_id'] FINAL CLEANUP
。
示例:
查询子句
在创建 ReplacingMergeTree
表时需要与创建 MergeTree
表时相同的 子句。
创建表的已弃用方法
在新项目中不要使用此方法,如果可能,请将旧项目切换到上述描述的方法。
除 ver
外的所有参数在 MergeTree
中具有相同的含义。
ver
- 版本列。可选参数。有关描述,请参见上述文本。
查询时间去重 & FINAL
在合并时,ReplacingMergeTree 识别重复行,使用 ORDER BY
列的值(用于创建表)作为唯一标识符,保留唯一标识符的最高版本。然而,这仅提供最终正确性 - 并不保证行会被去重,您不应依赖它。因此,查询可能会由于更新和删除行被考虑在内而产生不正确的答案。
为了获得正确的答案,用户需要在后台合并的基础上补充查询时间的去重和删除。这可以使用 FINAL
操作符来实现。例如,考虑以下示例:
不使用 FINAL
的查询产生不正确的计数(确切结果将根据合并而有所不同):
添加 FINAL
产生正确的结果:
有关 FINAL
的进一步详细信息,包括如何优化 FINAL
性能,我们建议您阅读我们的 关于 ReplacingMergeTree 的详细指南。