♻️

DBT*incrementalでスキーマ変更時にfull refreshする方法

2023/09/08に公開

概要

DBT*Incrementalで運用している際に、スキーマ変更時に自動的にfull refreshする方法を記載。

https://docs.getdbt.com/docs/build/incremental-models

記事対象者

  • dbtに関する基礎知識を持っている方
  • incremental modelの運用で悩んでいる方

動作環境

  • dbt-snowflake: 1.5.2
  • Argo Workflow
  • GitLab CI/CD

解決したい課題

DBT*Incremental modelを運用する際に、スキーマを変更するケースが出てくる。
on_schema_changesync_all_columnsを使用することで、カラム削除と追加を行うことが可能だが以下の問題点が生じる。

  1. カラム追加の際、過去分のレコードの値が生成されない。
  2. 既存カラムに対してロジックが変更になった際、過去分のレコードの値は旧ロジックで生成されたままとなる。

課題を解決したい背景

自動化して解決する以前は、ステージング、本番環境に反映する度に担当者が手動でdbt run -fコマンドを使ってアップデートが必要なトイルとなってました。
また、この作業を忘れてしまい本番環境でエラーが生じてしまうケースも度々ありました。

課題解決の要件

  • 全ての作業が自動化される。
  • 各環境に反映される度に自動でdbt run -fが起動すること
  • 開発環境については自動化は必要ない

課題解決手法

  • ✅ GitLab CI/CDにて incremental model の差分を検知したら full refresh を行うようにする。
.gitlab-ci.yml
previous_commit=$(git log --merges --pretty=format:"%h" | sed -n '2p')
changed_files =$(git diff --name-only --diff-filter=AMCR ${privious_commit} | grep | '\.sql$' | xargs grep -l "is_incremental")

for file in $changed_files; do
  model=$(basename "$(file%.*)")
  if [[ -z "$models" ]]; then
    models="+$model"
  else
    models+=" +$model"
  fi
done

dbt run --select $models -f
# develop -> mainマージ時の previous_commit 取得コマンド
previous_commit=$(git log --merges --pretty=format:"%h" | grep "into 'main'" | sed -n '2p')

その他

  • ワークフロー実行時にスキーマの変更を検知して full refresh 行う方法も検討しましたが以下の理由でやめました。

    • SLA の関係上決まった時間までにデータを提供する必要がある。
      • full refresh は時間がかかる為、本番ワークフロー稼働より事前に行う必要がある。
    • スキーマ変更が伴わなくとも、既存ロジックが変更になることがある。
      • スキーマの変更を検知するロジックは比較的簡単だが、カラム生成ロジックの変更を検知することは難しい。
  • github actions ならchanged-filesを使えばもっと簡単に実装できます。

Discussion