dbt

dbt の state と defer を使った差分実行と CI 高速化

2026-04-19
NicheeLab編集部

変更のないモデルまで毎回フルビルドしていると、CI が遅くコストも高くなります。dbt の state と defer は、直近の実行状態を参照して差分のみを実行し、未選択の依存は既存の本番テーブルへ安全に参照させることで、CI を安定かつ高速にします。

本稿は公式ドキュメントの動作に基づき、試験に出やすい選択子の挙動や、CI 設計の落とし穴も含めて解説します。環境やバージョンに依存しやすい箇所は慎重に言及します。

state と defer で差分実行の全体像

dbt の state は、過去の実行で生成されたアーティファクト(通常は manifest.json など)を参照し、現在のリポジトリ状態と比較して変更を検出します。defer は、ビルド対象に含めない依存関係について、本番環境など既に存在するリレーションを参照先として解決します。

これにより CI では、変更されたモデルとその影響範囲だけを実行しつつ、上流を安全に本番へ委譲でき、待ち時間とリソース消費を大幅に削減できます。

  • state: 前回アーティファクトへのパスを指定して差分検出を行う
  • defer: 未選択の参照先を本番アーティファクト由来のリレーションに解決する
  • 組み合わせ: --state と --defer を同時に使うのが CI の定石

CI における state + defer の流れ

Git RepoCI Jobpushdbt build--state=prod_artifacts/ --deferProd artifactstarget/ manifest.json, etc.resolve refs to prod relationsrun only changed nodesstate:modified+

最小構成のコマンド例

dbt build \
  --state ./artifacts/prod \
  --defer \
  --select state:modified+

state の基礎と選択子の使い分け

state は前回実行のアーティファクトと比較して、どのノードが新規・変更かを判定します。代表的には、モデルの SQL、本体に作用する設定値、テスト定義の変更などが比較対象になります。マクロの変更は広範囲に影響し得るため、関連ノードが変更扱いになる可能性に注意します。

差分の選択はセレクタで制御します。特に、末尾のプラスは子方向(下流)を、先頭のプラスは親方向(上流)を含めるという直感的だが試験で問われやすいポイントを押さえておきましょう。

  • --state には前回の target/ 配下(例: target/manifest.json を含むディレクトリ)のパスを指定する
  • state:modified は「前回から変更あり」のノードを選ぶ
  • state:new は新規追加ノードのみを選ぶ
  • 末尾の + は子方向、先頭の + は親方向を含める(例: state:modified+ は変更ノードとその下流)
セレクタ含まれる範囲主な用途補足
state:modified変更されたノードのみピンポイントに変更分を実行テストは build で暗黙的に付随
state:new新規ノードのみ新しく追加したモデルの検証既存ノードは除外
state:modified+変更ノードとその子孫(下流)下流影響も含めて検証スキーマ互換性の確認に有効
+state:modified変更ノードとその祖先(上流)ソース〜変更点までの依存を再実行上流更新が必要な時に使用

変更検出だけを一覧(実行はしない)

dbt ls --state ./artifacts/prod --select state:modified

defer の基礎と参照解決の挙動

defer は、選択しなかった依存ノードの ref や source の参照先を、--state で与えたアーティファクトに記録された既存リレーションへ解決します。典型的には、本番環境で最後に成功した実行のアーティファクト一式を参照します。

これにより CI の一時スキーマでは上流を再構築せず、変更点のみを安全にビルドできます。ただし defer 先に該当リレーションが存在しない場合は参照エラーになるため、対象が本番で確実に存在することが前提です。

  • Core では --defer と --state を併用するのが基本
  • defer は参照解決の仕組みであり、実行対象の選択はセレクタで別途制御する
  • 本番と CI でターゲットスキーマやデータベースが異なっても、アーティファクトに記録された完全修飾名で解決できる

CI ターゲットで defer を使って変更分だけビルド

dbt build \
  --target ci \
  --state ./artifacts/prod \
  --defer \
  --select state:modified+

CI パイプライン設計パターン

実務では、本番実行で生成された target/ 配下(少なくとも manifest.json)が常に CI から参照できるように保管します。ワークフローとしては、本番ジョブの成功時にアーティファクトをストレージへ保存し、CI ではそれを取得して --state に渡します。

dbt Cloud では UI の設定で Production へ Defer でき、Cloud が内部的にアーティファクトを解決します。dbt Core の場合は手動でアーティファクトを用意します。

  • 本番ジョブ成功時に target/ をアーカイブして永続化
  • CI 開始時にそのアーカイブを取得・展開し --state に指定
  • CI 実行は state:modified+ を基本にし、破壊的変更時のみ範囲を広げる
  • ジョブ時間短縮のため partial parsing を有効化(互換バージョンで)

GitHub Actions の一例(概念)

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Restore prod artifacts
        run: |
          mkdir -p artifacts/prod
          aws s3 cp s3://my-bucket/dbt/prod/last_success/ ./artifacts/prod --recursive
      - name: Install dbt
        run: pip install dbt-core dbt-bigquery  # 例: ターゲットに合わせる
      - name: Build changed nodes with deferral
        run: |
          dbt build \
            --profiles-dir . \
            --target ci \
            --state ./artifacts/prod \
            --defer \
            --select state:modified+

落とし穴と検証戦略

スキーマ非互換の変更(列削除やデータ型変更)を defer で見逃すと、子モデルの実行時に失敗します。変更ノードの子孫まで実行する state:modified+ をデフォルトとし、破壊的変更が疑われる場合は +state:modified+ などで広めに網をかけます。

増分モデルでは、未選択の上流を本番へ defer しても、実データの新旧差分が意図どおりになるとは限りません。クリティカルな経路はフルリフレッシュや限定的な再計算の検討が必要です。

  • 末尾と先頭の + を取り違えない(子方向は末尾)
  • defer 先に存在しないリレーションは参照できない(事前に本番で存在を担保)
  • マクロ変更は広範囲に波及し得るため、変更検出結果を dbt ls で目視確認
  • build を使うと、選択したリソースに紐づくテストも合わせて実行できる

変更分のモデルとテストをまとめて検証

dbt build \
  --state ./artifacts/prod \
  --defer \
  --select state:modified+

試験対策の要点(Analytics Engineer)

試験では、state セレクタの意味、+ の向き、defer の目的と前提(既存リレーションの参照)を問うパターンが多いです。CI 文脈のシナリオ問題にも備え、適切なコマンド例をそのまま書けるようにしておきましょう。

  • state:modified+ は変更ノードとその下流。+state:modified は上流。
  • --defer は参照解決の切替であり、実行対象の選択は --select 側で行う。
  • --state は前回実行のアーティファクトディレクトリへのパス。
  • dbt build を使うとモデル・シード・スナップショット・テストを一括で処理。

書き慣れておくコマンド

dbt ls --state ./artifacts/prod --select state:modified

dbt build --state ./artifacts/prod --defer --select state:modified+

dbt build --state ./artifacts/prod --defer --select +state:modified+

問題で確認

Analytics Engineer

問題 1

本番に既存の上流テーブルがあり、CI では変更モデルとその下流のみを実行し、未選択の参照は本番を用いたい。最も適切なコマンドはどれか。

  1. dbt build --state ./artifacts/prod --defer --select state:modified+
  2. dbt build --select state:modified+
  3. dbt build --state ./artifacts/prod --select +state:modified
  4. dbt build --defer --select state:new

正解: A

要件は差分検出と本番への参照切替。--state と --defer を併用し、変更ノードと下流を含む state:modified+ を選ぶ A が適切。B は defer がない。C は上流を含めてしまい方針と異なる。D は新規ノードのみで要件に合わない。

よくある質問

state 用のアーティファクトは何を用意すればよいですか?

最低限 manifest.json を含む前回実行の target/ ディレクトリを用意します。実務では本番ジョブ成功時に target/ をアーカイブし、CI の --state にそのディレクトリを指定します。

defer は dbt Cloud と dbt Core で違いがありますか?

仕組みは同じですが、Cloud は環境設定で Production へ Defer 可能で、アーティファクトの取得を内製で扱います。Core は --defer と --state を自分で指定し、アーティファクトの保管・配布をパイプラインで実装します。

マクロを変更した場合、state:modified にどこまで反映されますか?

マクロの変更はそれを介してコンパイルに影響するノードで変更検出される可能性があります。影響範囲が広がる場合があるため、変更直後は dbt ls --state ... で選択結果を確認し、必要に応じて選択範囲を広げて実行してください。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.