深入理解 dbt 增量模型

meicanhong發表於2023-01-01

想要實現資料增量寫入資料庫,可以選擇 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 模型的流程。

相關文章