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