Google Data Fusion中BigQuery表插入/更新场景下保留inserted_at字段仅插入需求咨询
嘿,这个需求我之前在做Data Fusion项目的时候刚好碰到过,给你几个实际可行的思路,不用纠结Lookup的性能问题:
自定义BigQuery Sink的MERGE语句(首推方案)
Data Fusion的BigQuery Sink在Upsert模式下,默认会生成覆盖所有字段的MERGE语句,但其实你可以自定义这个逻辑来跳过inserted_at的更新。具体操作步骤:- 在BigQuery Sink的配置面板里,切换到「Upsert」模式,然后找到高级设置里的「Custom Merge Statement」选项(不同版本的Data Fusion可能位置略有差异,多找找高级配置区就行)。
- 手动编写MERGE语句,核心是更新分支里不包含
inserted_at字段,只有插入分支才写入该字段。举个实际的例子,假设你的主键是user_id,其他业务字段是username、phone,目标表是my_project.my_dataset.user_table,Data Fusion传递的源数据临时表默认是S,语句可以这么写:
MERGE INTO `my_project.my_dataset.user_table` T USING S ON T.user_id = S.user_id WHEN MATCHED THEN UPDATE SET username = S.username, phone = S.phone -- 这里刻意不写inserted_at的更新逻辑,保留目标表原有的值 WHEN NOT MATCHED THEN INSERT (user_id, username, phone, inserted_at) VALUES (S.user_id, S.username, S.phone, CURRENT_TIMESTAMP()) -- 如果你的源数据里已经有inserted_at的初始值,也可以换成S.inserted_at这样配置后,更新操作就不会改动
inserted_at字段,只有第一次插入时才会设置它的值。用BigQuery触发器兜底(简单粗暴的方案)
如果你觉得自定义SQL有点麻烦,也可以直接在BigQuery的目标表上创建一个DML触发器,强制在更新时保留原inserted_at的值。比如:CREATE OR REPLACE TRIGGER preserve_inserted_at_trigger BEFORE UPDATE ON `my_project.my_dataset.user_table` FOR EACH ROW SET NEW.inserted_at = OLD.inserted_at;这个触发器会在每次更新操作触发时,把新的
inserted_at值强制替换回原来的旧值,相当于直接锁死了这个字段的更新权限。不过要注意,如果你处理的数据量特别大,触发器可能会带来一点点性能开销,但在BigQuery的架构下这个影响基本可以忽略。(不推荐)避开Lookup的折中方案
你提到不想用Lookup组件因为目标表数据量大,这个方案确实性能一般,但还是提一下作为备选:可以在Data Fusion pipeline里加一个「BigQuery Execute」组件,提前查询目标表的主键和inserted_at字段,然后和源数据做左连接。这样更新时就用查询到的旧inserted_at值,插入时用新值。但这个操作会涉及到大表的查询和关联,数据量一大就容易卡壳,所以还是优先前两个方案。
备注:内容来源于stack exchange,提问作者Oussama NEZAR

