♻️
DBT*incrementalでスキーマ変更時にfull refreshする方法
概要
DBT*Incrementalで運用している際に、スキーマ変更時に自動的にfull refreshする方法を記載。
記事対象者
- dbtに関する基礎知識を持っている方
- incremental modelの運用で悩んでいる方
動作環境
- dbt-snowflake: 1.5.2
- Argo Workflow
- GitLab CI/CD
解決したい課題
DBT*Incremental modelを運用する際に、スキーマを変更するケースが出てくる。
on_schema_changeのsync_all_columns
を使用することで、カラム削除と追加を行うことが可能だが以下の問題点が生じる。
- カラム追加の際、過去分のレコードの値が生成されない。
- 既存カラムに対してロジックが変更になった際、過去分のレコードの値は旧ロジックで生成されたままとなる。
課題を解決したい背景
自動化して解決する以前は、ステージング、本番環境に反映する度に担当者が手動で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 は時間がかかる為、本番ワークフロー稼働より事前に行う必要がある。
- スキーマ変更が伴わなくとも、既存ロジックが変更になることがある。
- スキーマの変更を検知するロジックは比較的簡単だが、カラム生成ロジックの変更を検知することは難しい。
- SLA の関係上決まった時間までにデータを提供する必要がある。
-
github actions ならchanged-filesを使えばもっと簡単に実装できます。
Discussion