立ち上げ時 5モデル → 半年で 200モデル → ビルドが3時間。「 順調なプロジェクトほどぶつかる壁」。マテリアライゼーション設計と並列度・incremental の組み合わせで現実的な時間に戻せます。
あの時こうすれば良かった、と思う症状
・夜中の dbt run が朝7時にもまだ走ってる / ・PR が出るたび dev run で30分待ち / ・「 クレジット今月超えそう」 / ・「特定の1モデルが1時間かかってる」
起きる仕組み(よくある原因 TOP6)
- 1全モデル `view` :簡単だが、下流で何度も再計算される
- 2全モデル `table`:毎回フルリビルドで時間爆発
- 3incremental の設計ミス:merge key・where 句が無く、結局フル
- 4threads 設定不足:`threads: 4` のまま、warehouse の容量があるのに並列化されてない
- 5長い依存チェーン:parent → child → grandchild と直列で待ち
- 6遅い1モデル:window function や large self-join がある巨大モデルがビルド全体のボトルネック
調査手順
- `dbt run --output json` + dbt-artifacts でモデル別所要時間
- Elementary / Datafold:実行時間トレンド・依存グラフを可視化
- dbt docs:依存グラフの DAG 直列度をチェック
- 個別モデルの実行計画: `--dry-run`、Snowflake `EXPLAIN`
- スレッド利用率:`threads` 設定 vs 実行中の同時クエリ数
対策(マテリアライゼーション戦略)
| タイプ | 用途 | 速さ | コスト |
|---|---|---|---|
| view | クエリ数少・最新性必須・小データ | クエリ時遅い | ストレージ¥0 |
| table | 再計算の元・中規模・複数ダウンストリーム | ビルド時遅い・クエリ速い | ストレージ消費 |
| incremental | 巨大データ・差分追加 | ビルドも速い | 管理コスト中 |
| ephemeral | 中間 の一部、独立テーブル不要 | 依存先で展開 | ストレージ¥0 |
| materialized view (Snowflake) | リアルタイム + 軽量集計 | クエリ速い | 計算費用継続 |
incremental の設計
良い incremental(`is_incremental()` + 期間絞り)
SQL
{{ config(materialized='incremental', unique_key='order_id') }}
SELECT *FROM {{ ref('stg_orders') }}{% if is_incremental() %} WHERE updated_at > (SELECT MAX(updated_at) FROM {{ this }}){% endif %}並列度の上げ方
- `threads: 16〜32`:warehouse がスケール対応していれば
- Snowflake の Multi-cluster Warehouse:threads 増 + 自動スケール
- BigQuery 予約スロット:on-demand から flex で並列実行枠を予約
- 長い直列の解消:依存を見直し、tag 別実行で並列化
- 重い1モデルの分割:window function を別モデルに切り出して再利用
ふくふくの進め方
dbt パフォーマンス診断は2週間で実施。① `dbt-artifacts` で実行時間トップ20モデルを抽出 ② `incremental` 化と分割の PR を提出 ③ threads / warehouse 設定の最適化。「3時間 → 30分」を月1〜2件のペースで実現してきました。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。