配置Dataform增量表:匹配时仅插入新行不执行更新
实现dbt增量模型仅插入无重复新行(保留SELECT预览)
要实现匹配到uniqueKey时不更新、仅插入新行的需求,不需要自定义merge操作(避免失去SELECT语句的预览优势),可以通过在SELECT语句中过滤掉已存在的重复记录来实现,具体方案如下:
核心思路
利用dbt增量模型的特性,在增量运行时,从源数据中筛选出目标表中不存在对应uniqueKey的记录,只将这些新数据插入目标表,完全保留原SELECT语句的结构和预览功能。
修改后的代码示例
type: "incremental", uniqueKey: ["alarm_number"], bigquery: { partitionBy: "DATE(alarm_time)", clusterBy: ["alarm_number", "location", "element"], updatePartitionFilter: "time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 4 DAY)" } } pre_operations { DECLARE trigger_checkpoint DEFAULT ( ${when(incremental(), `SELECT MAX(time) FROM ${self()}`, `SELECT TIMESTAMP("2020-01-01")`)} ) } SELECT s.*, FALSE AS notified -- 该字段不会因重复行被更新,因为重复行根本不会被选中 FROM ${ref("source")} s -- 增量过滤:只取源数据中时间晚于 checkpoint 的记录(优化同步效率) WHERE s.time >= trigger_checkpoint AND s.deviation >= 1.1 -- 关键过滤:排除目标表中已存在的 alarm_number AND NOT EXISTS ( SELECT 1 FROM ${self()} t WHERE t.alarm_number = s.alarm_number )
关键说明
- 保留SELECT预览优势:整个逻辑都在SELECT语句中实现,没有修改dbt默认的merge行为,依然可以正常预览SELECT的输出结果。
- 效率优化:结合
trigger_checkpoint的时间过滤,先缩小源数据的范围,再通过NOT EXISTS排除已存在的uniqueKey,避免全表扫描,适配BigQuery的分区/集群配置。 - uniqueKey的作用:这里的
uniqueKey依然可以用来做dbt的重复检测,但因为我们已经提前过滤了重复记录,实际运行时不会触发更新操作,只会插入新行。
替代方案(不推荐,会丢失预览)
如果一定要通过自定义merge操作实现,可以在模型配置中添加merge_update_columns: [](空数组),这样dbt生成的merge语句会在匹配到uniqueKey时不执行任何更新,仅插入新行。但这种方式会导致SELECT语句的预览结果包含重复行(因为没有提前过滤),失去预览的实际意义:
type: "incremental", uniqueKey: ["alarm_number"], merge_update_columns: [], -- 空数组表示匹配到不更新任何字段 bigquery: { partitionBy: "DATE(alarm_time)", clusterBy: ["alarm_number", "location", "element"], updatePartitionFilter: "time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 4 DAY)" } }
内容的提问来源于stack exchange,提问作者Khanetor
相关产品推荐
相关产品推荐

