dbt

dbt Slim CI実践ガイド: state:modified+ で差分だけ安全に流す

2026-04-19
NicheeLab編集部

本稿は、dbtのSlim CIを「state:modified+」で実装し、プルリクエスト(PR)で変化したモデルとその下流だけを素早く検証するための実務ガイドです。

Analytics Engineer認定でも頻出の、state選択・defer・アーティファクト運用の要点を、現場の落とし穴とあわせて解説します。

Slim CIの狙いと全体像

Slim CIは、前回の安定状態(本番のアーティファクト)と比較して変更が入った対象のみをCIで実行し、レビューを高速化する手法です。dbtでは state:modified を選択子に使い、さらに + を付けて下流も含めることで、影響範囲の検証を短時間に絞り込みます。

Slim CIの核は「前回の状態」を示すアーティファクト(典型的には本番のmanifest.json)です。CIはこれを --state オプションで読み込み、ローカルの変更点と比較します。実行時には --defer を併用し、選択外の参照先は本番に委譲します。これにより、変更していない上流をCIで再作成せずに、テストを正しく実行できます。

  • state:modified+ は「変更されたノードとその下流」を選択
  • --state は比較元(本番のmanifest.jsonなど)を指定
  • --defer は未選択ノードの参照解決を本番アーティファクトに委譲
  • dbt build を使うとモデル・スナップショット・シード・テストまで一括実行
実行方式対象範囲主なメリット主なリスク/注意点
フル実行(dbt build)全リソース回帰の取りこぼしが少ない時間/コスト増。PRごとには非現実的
影響範囲実行(A+)指定Aとその下流依存先の検証を確保Aの変更判定が人手だと漏れや過剰選択が起きやすい
Slim CI(state:modified+ --defer)変更分とその下流のみ最速のPR検証。本番を参照しつつ正確に差分実行本番アーティファクトの取得・保全が前提。設定ミスで選択漏れの恐れ

Slim CIのデータフロー(概念図)

PRブランチ                 CIランナー                     本番(前回成功状態)
    |  変更 (SQL/モデル)         |                                 |
    |--------------------------->| 1. 本番の manifest.json 取得     |
    |                            |<---------------------------------|
    |                            | 2. dbt build -s state:modified+ --defer --state=./state
    |                            |    ├─ 変更ノードを選択
    |                            |    ├─ 下流も含めて実行/テスト
    |                            |    └─ 未選択の参照は本番に委譲
    |                            |                                 |
    |<---------------------------| 3. 結果(成功/失敗・アーティファクト)

state:modified+ の仕組みと周辺オプション

state:modified は、--state で指す過去のアーティファクト(一般に manifest.json)と現在のプロジェクト定義を比較し、差分があるノードを選びます。差分には、SQLやschemaファイルの定義変更、新規追加、パスやconfigの変更などが含まれます。末尾の + は、選択されたノードの子孫(下流)も含める指定です。

Slim CIではこれに --defer を組み合わせます。--defer は、選択されなかったref()/source()解決を --state のリレーションに委譲し、未変更の上流をCIで再作成しないようにします。これにより、テストも本番データを参照して成立します。

  • dbt ls -s state:modified+ で対象一覧を事前確認できる
  • 新規ノードは state:new で明示選択も可能(例: dbt build -s state:new+)
  • --indirect-selection=eager を付与すると、関連テストの取りこぼしを抑制しやすい
  • アーティファクト比較はファイル内容・依存情報を基に行われるため、単純なタイムスタンプ比較ではない
選択子意味主な用途
state:modified前回状態から変更されたノードPR差分の最小実行
state:modified+変更ノードとその下流影響範囲を含む差分実行(推奨)
state:new前回に存在しない新規ノード新規追加のみの検証やリリース直後確認

実装手順(GitHub Actions + dbt Coreの例)

本番で成功したパイプラインから manifest.json(必要に応じて run_results.json も)を成果物として保存し、PRのCIで取得します。CIはそのアーティファクトを --state に指定し、--defer を有効化して差分のみを実行します。

SnowflakeやDatabricksなどの接続情報はリポジトリシークレットで注入します。並列実行やキャッシュは環境に合わせて調整してください。

  • mainブランチ成功時に target/ 配下をアーティファクト化(少なくとも manifest.json)
  • PR CIでそのアーティファクトをダウンロードし、--state で参照
  • dbt build -s state:modified+ --defer --indirect-selection=eager を実行
  • 必要に応じて dbt ls で対象をログに出し、選択の妥当性をレビュー可能化

GitHub Actions(抜粋)

name: pr-slim-ci
on:
  pull_request:
    branches: [ main ]
jobs:
  slim-ci:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dbt
        run: |
          pip install --upgrade pip
          pip install dbt-core dbt-snowflake  # 使うアダプタに合わせて変更

      - name: Download prod artifacts
        uses: actions/download-artifact@v4
        with:
          name: prod-target-artifacts
          path: state/

      - name: Show planned selection
        run: |
          dbt --version
          dbt deps
          dbt ls -s 'state:modified+' --state state | tee selection.txt

      - name: Slim CI build
        env:
          DBT_PROFILES_DIR: ./.profiles  # 適宜
          SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}
          SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }}
          SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
        run: |
          dbt build -s 'state:modified+' \
            --defer --state state \
            --indirect-selection=eager \
            --target ci

      - name: Upload CI artifacts
        uses: actions/upload-artifact@v4
        with:
          name: pr-ci-target
          path: target/

よくある落とし穴と検証ポイント

アーティファクトの取り違えは最大の落とし穴です。PRブランチで直前に生成したmanifest.jsonを --state に渡すと、差分が検出されず、意図せず未検証となることがあります。必ず「本番で最後に成功した」アーティファクトを使います。

マクロやパッケージの変更は、モデルに影響する場合があります。state比較は依存関係も見ているため、多くのケースで変更が伝播しますが、レビューでは dbt ls の結果を確認し、テストの取りこぼしがないかを見るのが安全です。

  • --state は本番のmanifest.jsonを指すこと。PR生成物を参照しない
  • --defer を忘れると、未選択の上流までCIで再作成してしまい、時間/コストが膨張
  • ソース定義や契約(contracts)変更は下流の再検証が必要。state:modified+ で捕捉されるか ls で確認
  • シードやスナップショット変更は build に含まれるが、選択漏れがないか注意
  • 間接選択は明示的に --indirect-selection=eager を推奨(関連テストの網羅性向上)
事象原因対処
差分が0件になる--state が誤ってPR生成物を参照本番のmanifest.jsonに差し替え、dbt lsで再確認
テストが不足間接選択が保守的--indirect-selection=eager を付ける / 選択範囲に + を追加
実行が遅い--defer 不足や選択過多--defer を有効化、state:modified+ に絞る

本番アーティファクトの保管とセキュリティ

manifest.json はモデル定義やリレーション名などのメタデータを含みます。一般にPIIは含みませんが、スキーマ名・テーブル名などの内部情報は含まれるため、公開範囲を制御し、リポジトリアクセス権限を適切に設計します。

保存場所はCI/CDのビルドアーティファクト、オブジェクトストレージ、もしくはdbt Cloudの前回ランからの取得などが一般的です。アーティファクトのライフサイクル(保持期間、ローテーション)を決め、必ず最後に成功したバージョンを参照できるようにします。

  • 最小権限のストレージに保存し、PRから読み取り専用で取得
  • アーティファクト名やパスは固定化し、取り違えを防止
  • 保持期間はリリースサイクルに合わせて設定(例: 30〜90日)
  • dbt Cloud利用時は前回成功ランのArtifacts API活用を検討

試験対策チェックリスト(Analytics Engineer)

試験では、変更のあるモデルとその下流のみをCIで実行する最適解を選ばせる設問がよく出ます。state:modified+ と --defer の組み合わせをキーワードとして押さえ、--state で参照するアーティファクトが「本番の前回成功状態」である点を明言できるようにしましょう。

選択子の違い、build と run の使い分け、ソースやシード・スナップショットの扱いも要確認です。

  • state:modified と state:new の違いを説明できる
  • + の意味(子孫選択)を説明できる
  • --defer の効果を説明できる(未選択のref/source解決を本番に委譲)
  • dbt build はモデル・シード・スナップショット・テストを包括実行
  • dbt ls で選択結果を検証できる

問題で確認

Analytics Engineer

問題 1

PRで1つの中間モデルを変更した。CIでは変更モデルとその下流だけを検証し、未変更の上流は本番データを参照したい。最も適切なdbtコマンドはどれか。(本番のmanifest.jsonは ./state にある)

  1. dbt build -s state:modified+ --defer --state ./state
  2. dbt run --select +state:modified --state ./state
  3. dbt test -s state:new+ --defer --state ./state
  4. dbt build -m tag:ci --defer

正解: A

Slim CIの基本は state:modified+ で差分と下流を選択し、--defer で未選択参照を本番に委譲、--state で比較元アーティファクトを指定する。よってAが正解。Bは順序と記法が不適切、Cは新規ノードのみ、Dはstate指定がなく選択もタグ依存で要件を満たさない。

よくある質問

マクロを変更した場合、state:modified+ は影響を受けたモデルを選べるか?

多くのケースで、マクロ依存の変更はモデル差分として検出されます。とはいえプロジェクト構成や依存解決により挙動が異なる場合もあるため、CIで dbt ls -s state:modified+ --state を併用し、対象が妥当かを確認するのが安全です。

ソース定義(schema.ymlのカラム型やtests)を変えたときはどうなる?

ソースのメタ定義変更は、その下流テストやモデルに影響し得ます。state:modified+ は該当するノードと下流を選ぶ前提ですが、取りこぼしを避けるため、PRでは選択結果をログに出してレビューする運用を推奨します。

--defer を使うと本番を上書きしないか?

--defer は未選択ノードの解決を本番アーティファクトに委譲するだけで、本番オブジェクトを変更しません。選択されたノードのみ、CIターゲット(例: 別スキーマ)で実行されます。ターゲットの分離(専用スキーマ/DB)を徹底してください。

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

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.