dbt差分があるモデルだけ加工しようとしたらちょっとハマった話
背景
筆者のデータ基盤の軽い説明や表題に関連するやりたいことを書いていきます。
まず環境をざっと書くと以下の感じ
- データ基盤は基本snowflake上に乗っかっている
- データの加工はdbtでやっている
以上のような環境で、最近は開発環境をよくしたりデータオブザーバビリティを向上させたりといったことに注力していきたいと考えていました。その一環で、まずはdbtのモデル開発時、リリース前にCIでdbt run
を走らせれるようにすることを実現できるよう動いていました。
なんでそんなことやろうとするの?というと、弊社のdbtの開発環境は、手元から開発環境用に用意されたsnowflakeのデータベース上でdbt run
を実行できるようになっていて、開発中は主にそこで動作確認をしていたのですが、リリースしてから dbt run
に失敗することに気づいて急いで修正パッチを当てるということがちょこちょこ起きていてそこに課題を感じていました。
本番での加工に失敗したのに気づいてから修正しても再度本番でdbt run
し直す必要があるため余計な手間が掛かるし、修正に時間がかかればかかるほど対応がめんどくさくなっていきます。
そのため、リリースをする前に変更を加えたモデルの加工が成功するか試せるような環境をCIで構築したいと考えていました。
state:modifed
で差分があるモデルだけ加工する
CIで毎回全てのモデルの加工を走らせていては時間もかかりますし、コンピュートリソースを無駄に使うことになるのでお金ももったいないです。なので加工したいモデルだけ加工させたいですよね。
そんなときに便利なのが state:modified
というモデルの選択の方法です。
dbtコマンドを実行する際に --select 'state:modified' --state /path/to/state
とすることで、--state
で指定したディレクトリに置かれたmanifest.jsonと実行時に生成されるmanifest.jsonを比較して、差分があるモデルだけ加工を走らせてくれるというまさに今回のようなユースケースにはうってつけのセレクターメソッドが用意されていました。
ちなみに state:modified+
とすることで差分があるモデルに依存するモデルも選択することができます。変更したモデルに依存したモデルもちゃんと加工できるかな?は気になるポイントなので自分はつけてます。
比較するマニフェストファイルの用意をどうしてるか
今回の本題的にあまり大事な話ではないのであまり詳細には書きませんが、state:modified
を使うときは比較する用のマニフェストファイルを用意する必要があります。今回は本番で動いている最新のマニフェストファイルと比較がしたいのでそいつをCI上で扱えるようにします。具体的にどうしてるかというと
- PRをmasterへmergeした際に
dbt compile
をし、s3にtarget/
の中身をアップロードする - CIで差分だけビルドするワークフローの最初にs3からmanifest.jsonを取ってくる
という感じでそんな複雑なことはしてません。
変更を加えてないモデルも加工が何故かされてしまう
state:modified+
でやりたいことできるやん!勝った!第3部完!って感じでおもむろに適当なモデルに適当な変更をしdbt run --select 'state:modified+' --state /path/to/state
をしてみたのですが、現実はそんなに甘くありませんでした。
なぜか変更してないモデル(しかも全部じゃない)も加工が走っていてどういうこと????となりました。
原因
manifest.jsonとにらめっこしたりドキュメントを読み漁ったりした結果、原因はこれでした。
筆者のデータ基盤も、めちゃめちゃ量が多い生ログから対したサイズじゃないデータまで色々扱うのでモデルごとにsnowflakeのwarehouseを指定できるような状態にしていました。
で、モデルのconfigでsnowflake_warehouse=xxxx
とwarehouseを指定する記述をすると、manifest.jsonの各モデルのメタデータが記述されている部分にwarehouseに関する記述も反映されます。
{
"model.hoge.huga": {
// 本来は他にも色々フィールド生えてるけどみやすさのために抜粋
"config": {
// 本来は他にも色々フィールド生えてるけどみやすさのために抜粋
"snowflake_warehouse": "XXXXX_WH_S",
}
}
}
このsnowflake_warehouse
の設定が、本番とCIで違うために差分があるとみなされて加工が走っていたというのが原因でした。
差分を見る対象を絞る
上記の問題をどう解消したかというと、マニフェストファイルの中で差分を見る範囲を絞ることで解決しました。
公式ドキュメントを読むとmanifest.jsonのどの部分を見ているかというのが説明されています。
今回はモデルやテスト、マクロのSQLに変更があったときに加工が実行されてくれればいいのでstate:modified.body
とstate:modified.macros
を指定することにしました。
Discussion