深入理解 dbt 增量模型

时间:2023-01-01 15:07:58

想要实现数据增量写入数据库,可以选择 dbt 增量模型。通过 dbt 增量模型,我们只用专注于写日增 SQL,不用去关注于如何安全的实现增量写入。

dbt 增量模型解决了什么问题

  • 原子性写入:任何情况下,增量写入只有一个程序在写入。

假设增量程序已经上线,线上增量程序在执行的同时,开发也在本地执行增量程序。俩分程序同时执行,难以保证线上数据的正确性。

如何使用 dbt 增量写入

{{config(
    materialized='incremental',
    unique_key=['unique_key', 'time_column'],
    incremental_strategy='merge'
)}}
    
select * 
from table
where time_column >= date_add('day', -1, current_timestamp) 

dbt 执行增量写入流程

  • delete + insert
    • drop if exists tmp_table
    • create tmp_table as ( incremental sql )
    • delete from table where file in ( select file in tmp_table ) and file2 in ....
    • insert into table select * from tmp_table
  • merge
    • drop if exists tmp_table
    • create tmp_table as ( incremental sql )
    • merge into table use tmp_table

delete + insert 的增量流程是有问题的

  • 会出现原表中的数据被删除但新的数据没进来的情况
    • 例如程序A执行完 delete 操作,程序B 执行完 drop tmp_table,此时程序A insert 是失败的,于是就导致了旧数据被删除了,但新数据没插入的情况。
  • 表是有一段时间查不到数据
    • 因为 delete 和 insert 是俩步操作,在<delete, insert> 这间隔内,此时查询表内数据,是查不到数据的。

但 merge 模型下的增量写入就没有上述的问题,原因是 merge 是原子性操作,所以更新数据时候不会存在删数据和插数据的间隔,于是就能避免以上问题。

dbt 创建tmp表也是一个很妙的地方,通过 tmp 表能实现增量写入是原子操作

例如在 merge 模式下,并发执行增量程序,会出现以下执行异常:

  • tmp_table is exist
    • 俩程序在同时在执行 create_tmp,执行慢的那个便会创建 tmp 表失败,于是便没有 merge 操作。
  • tmp_table is not exist
    • 程序A 创建好的 tmp 表,被程序B drop 掉。于是程序A的 merge 操作失败,程序B 继续执行。

通过以上俩个异常,能保证 dbt 不管在什么情况下,只有一个增量程序在执行。

总结

以上便是 dbt 增量模型的一些细节,我们在选择 dbt 做增量时,要尽量选择 merge 模式。如果是自己想要实现增量写入,也可以参考 dbt merge 模型的流程。