在執行完 dry-run、確保 SQL 程式碼可被執行後,就會在測試/正式環境中執行異動的 dbt models,因為 CI 和 CD 的步驟有些不同,以下分為兩部分來介紹。
在 CI 時,會在測試環境中執行異動 models,但測試環境的 models 只會在 CI 時執行,日常排程不會執行。
因此測試環境的資料可能沒有被更新到,在執行異動的 models 前必須要更新上游的資料源。
以下是調整前後的 dbt 指令
# 僅執行異動 models 和其下游
dbt run --select "state:modified+" --state base --target ci --target-path target
# 執行異動 models 和其上下游
dbt run --select "@state:modified" --state base --target ci --target-path target
但更新上游資料源會衍生出另一個問題:每次 CI 會需要跑很多 models,會導致成本增加。
在某次看 dbt 文件時,意外發現到 dbt defer 的功能,可以解決成本增加問題,以下就介紹 dbt defer 以及如何使用
dbt defer 用於在不同的環境(如測試環境和正式環境)之間共享或重複使用資料模型,能避免重新運算某些模型。
# model_A
SELECT *
FROM {{ ref('model_B') }}
上述案例在測試環境中 compile 結果如下
SELECT *
FROM ci_env.model_B
但使用 defer,model_B 如果有存在正式環境,compile 結果會變成
SELECT *
FROM prod_env.model_B
當 CI 時使用的資料源是正式環境的 models,就不需要特別重跑資料源,能省下不少運算成本。
在使用 defer 前,需要產生正式環境 manifest,並指定存放的資料夾(避免被覆蓋掉),dbt 才能去找正式環境有沒有對應 models。
dbt parse --target base
接下來就是在 dbt run 時加上 —defer,並且在 —state 輸入剛剛存正式環境 manifest 的資料夾
dbt run --select model_A+ --target-path target --state base --defer
但以上的指令在運行時仍有可能使用測試環境的上游 models(只有測試環境沒有該 model 才會使用正式環境的),需要加上 —favor-state,就能讓 dbt 優先使用正式環境的 models。
因為上游是使用正式環境的 models,就不需要重跑(每日排程都會執行),可以省去龐大的運算時間及資源。
在 CD 時,會在正式環境中執行異動 models,因為正式環境的 models 每日排程都會更新,所以不需要重跑上游的資料源,步驟相較於 CI 階段簡單許多:
# 僅執行異動 models 和其下游
dbt run --select "state:modified+" --state base --target prod --target-path target
以上介紹了 CI/CD 執行異動 models 的步驟,並使用 dbt defer 來減少 CI 時間及成本,接下來的幾篇文章將會介紹在 CI 最後做的客製化檢查。