ORDER BY 部分,而不是 PRIMARY KEY) 的重复条目。
数据去重只会在合并期间发生。合并会在后台于未知时间执行,因此你无法提前规划。部分数据可能仍未处理。虽然你可以使用 OPTIMIZE 查询触发一次非计划合并,但不要依赖这种方式,因为 OPTIMIZE 查询会读写大量数据。
因此,ReplacingMergeTree 适合在后台清理重复数据以节省空间,但不能保证完全不存在重复数据。
有关 ReplacingMergeTree 的详细指南 (包括最佳实践以及性能优化方法) 可参见此处。
创建表
行的唯一性由表中的
ORDER BY 部分决定,而不是 PRIMARY KEY。ReplacingMergeTree 参数
ver
ver —— 版本号列。类型为 UInt*、Date、DateTime 或 DateTime64。可选参数。
合并时,ReplacingMergeTree 会在所有排序键相同的行中只保留一行:
- 如果未设置
ver,则保留选集中最后一行。选集是指参与合并的一组 parts 中的一组行。最近创建的 part (即最后一次 insert) 会是选集中的最后一个。因此,去重后,对于每个唯一的排序键,都会保留最近一次 insert 中的最后一行。 - 如果指定了
ver,则保留版本号最大的一行。如果多行的ver相同,则对这些行应用“未指定ver”时的规则,也就是说,会保留最近 insert 的那一行。
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。如果某个分区中的所有 parts 都早于min_age_to_force_merge_seconds,ClickHouse 会将它们 全部合并为一个单独的 part,并移除所有删除行。 -
手动运行
OPTIMIZE TABLE table [PARTITION partition | PARTITION ID 'partition_id'] FINAL CLEANUP。
查询子句
ReplacingMergeTree 表时,需要使用与创建 MergeTree 表时相同的子句。
查询时去重 & FINAL
ORDER BY 列的值 (用于创建表) 作为唯一标识来识别重复行,并且只保留版本最高的那一行。不过,这只能保证最终正确性——并不保证这些行一定会被去重,因此你不应依赖它。因此,由于查询时会将更新行和删除行也计算在内,查询结果可能会不正确。
为了获得正确结果,用户需要将后台 合并 与查询时去重和删除移除结合起来。这可以通过 FINAL 操作符实现。例如,考虑以下示例:
FINAL 查询会导致计数不准确 (具体结果会因合并情况而异) :
FINAL 的更多信息,包括如何优化 FINAL 的性能,建议阅读我们的ReplacingMergeTree 详细指南。