问题
- 批量加载时的单表原子性:一种常见做法是先插入临时 partial key,再将记录复制到实际 key,并删除临时记录。这种方法性能较差——尤其是删除这一步,可能会占用总操作时间的 90% 以上。
- 多表一致性:当某个管道成功加载表 A、却在表 B 上失败时,表 A 已经提交,无法回滚。对这两张表进行跨表查询的分析人员会看到不同步的数据。
背景
INSERT 成功,该块中的所有行都会可见;如果失败,则一行都不会可见。不过,对于跨多个插入操作或多个表的数据,系统没有内置的原子提交机制。
当源表和目标表共享相同的存储策略时,分区操作命令 (MOVE PARTITION TO TABLE、REPLACE PARTITION、ATTACH PARTITION FROM) 是在元数据层面执行的。
这意味着无论数据量多大,它们的执行几乎都是瞬时的,因此非常适合作为原子交换模式的基础构件。
推荐方案
单表原子性的分步操作
1
创建暂存表
使用与生产表相同的 schema、分区键、
ORDER BY 和存储策略。2
将数据插入暂存表
将插入操作执行在暂存表上,而不是生产表上。
3
如果插入失败,则清空后重试
清空暂存表,然后重新执行加载。生产表中的数据不会受到影响。
4
如果插入成功,则将分区移到生产表
要将数据移入生产表并将其从暂存表中移除,请使用 或者,使用 这两种操作都属于相同存储策略下的元数据级变更,几乎会瞬间完成。
MOVE PARTITION。ATTACH PARTITION 将数据复制到生产表中的现有分区。5
清理暂存表
在所有分区都已移走后,清空暂存表,以便它在下一次加载时保持为空。
多表一致性
要求和限制
MOVE PARTITION TO TABLE、REPLACE PARTITION 和 ATTACH PARTITION FROM,源表和目标表必须满足以下条件:
- 具有相同的列结构
- 具有相同的分区键、
ORDER BY键和主键 - 具有相同的存储策略
- 目标表必须包含源表中的所有索引和投影
示例
参考
- 管理分区和 parts
- 有关此策略的更多信息,请参阅博文 为大规模 ClickHouse 数据加载提速 - 第 3 部分:让大规模数据加载更具弹性.