数据表的字段大概这样:
date: 数据时间(主键)
coutry: 国家 (主键)
app: 应用名(主键)
clicks: 点击数 (整数
spends: 花费的金额 (浮点数)
第三方 API 提供的历史数据可能有变化,需要及时处理,以便于报表能够及时更新
比如:
今天是 2022 年 10 月 15 日,但 2022 年 1 月 1 日~2022 年 1 月 10 日的历史数据需要更新
那应该先删除 2022 年 1 月 1 日~2022 年 1 月 10 日的历史数据,再插入该时间范围新的数据
该时间范围数据更新操作,产生了下面三种情况:
我的思考过程:
该方案有问题,比如数据时间范围是 2022 年 1 月~2022 年 12 月,版本号是 1
这时候删除+插入 2022 年 6 月的数据,版本号是 2
如果我按照 2022 年 1 月到 2022 年 12 月聚合数据,我得咋查出来啊??
再就是没办法表示已经删除的数据,除非增加一列,is_deleted ,问题是我怎么查询。。。
该方案的问题在于,删除数据是要删除比当前时间小的数据,那么问题来了 假如有这种情况: 任务 1 一共 100 条数据,插入了 50 条还没插完,这时候任务 2 开始执行了 因为任务 1 的更新时间要小于任务 2 ,任务 2 会先执行删除操作,所以会不会出现删不全的数据?
![]() |
1
yongjing 159 天前
没有 clickhouse 使用经验,不过大数据仓库都类似。
大概搜了一下,针对前两种情况,表引擎采用 ReplacingMergeTree ,做一次 insert 就好。 第三种情况,查不到的数据,如果不要求回溯,从表里直接删除就好。加版本号方案也没问题,自己权衡吧。 |
2
reter 158 天前 ![]() 如果数据时间的精度是日,那就比较好办, 如 #1 所说,使用 ReplacingMergeTree
把所有操作都转换成插入操作, 例如,删除操作可以转换为插入 clicks 和 spends 字段都为 0 的记录, 或者你想要的其他字段,用于覆盖旧记录。 用时间戳做版本号 ver (不要程序产生,用 sql 产生时间戳,为了保持 ver 近似单调递增) 查询时候可以认为, 主键相同的所有记录中,ver 最大的记录才是最终的记录:SELECT * FROM table1 GROUP BY 主键 ORDER BY ver LIMIT 1 |
![]() |
4
Maxwe11 158 天前
1 、至少是我个人没有看到过类似的最佳实践;
2 、clickhouse 是 olap 统计分析数据库,它只统计分析但是并不考虑数据本身的过多变化; 3 、参考 #2 楼朋友的描述,如果 clickhouse 不变,那么就增加一列 insert_time ,不用去刻意删除历史数据,统计的时候以最新 inserttime 为准,就是同时间周期的 max(insert_time)数据的聚合。 |