dbt

dbtで実現するBlue/Greenデプロイ: スキーマ切替で安全リリース

2026-04-19
NicheeLab編集部

本番のダッシュボードを止めずにモデルを更新したい—その現実解が、スキーマを切り替えるBlue/Greenデプロイです。dbtはターゲットごとにスキーマを分けられるため、このパターンと非常に相性が良いです。

この記事では、ポータブルに使える「Routerスキーマ+Blue/Greenスキーマ」方式を軸に、実装例、運用の勘所、試験で問われやすいポイントをまとめます。内容はdbtの安定機能(targets、selectors、defer、state)と主要DWHの一般的な挙動に基づいています。

Blue/Greenデプロイをdbtでやる理由

dbtはプロファイルのtarget単位でスキーマを切り替えられるため、Blue(現行)とGreen(切替候補)に同じモデル群を並走させるのが容易です。新しいビルドはGreenで実行し、検証後に参照を切り替えれば、読み手(BI/アプリ)へ与える影響を最小化できます。

また、dbtのstate選択子とdefer機能を併用することで、変更箇所だけをGreenに再構築しつつ、未変更部分はBlueを参照して依存解決できます。これにより、切替のスピードと安全性を両立できます。

  • スキーマ単位での並走により、本番テーブルを直接置換しない
  • dbtの--deferとstate:modified+で差分ビルドを効率化
  • 失敗時は参照先をBlueに戻すだけで即時ロールバック可能

設計パターン: Routerスキーマで切替

実務で扱いやすいのは、Blue/Greenの実体スキーマと、利用者が参照する安定スキーマ(ここではRouterスキーマ)を分ける方式です。Routerスキーマにはビューを作成し、背後の参照先をBlueまたはGreenへ切り替えます。ビューのCREATE OR REPLACEは多くのDWHでメタデータ置換として扱われ、単一オブジェクトの置換は短時間かつ原子的に行われます。

留意点として、複数ビューを一括で絶対に同一瞬間に切り替えることは、DWHの機能に依存します。厳密な同時性が不要な可用性重視の分析系では、ビューを逐次置換しつつ、スキーマ互換性を維持する運用が現実的です。

  • 例: analytics_blue と analytics_green を実体、analytics をRouterとする
  • Routerのビューはモデル名を踏襲(下流の参照先は常にanalytics.<model_name>)
  • 切替はビュー再作成で実施。必要に応じてトランザクション境界を活用

Blue/GreenとRouterスキーマの構成

SELECT fromdbt build --target blue/greenBI / AppsanalyticsRouter(安定参照) (views)analytics_bluetables/materialanalytics_greentables/material

リリース手順(Blue→Green)

以下は、差分ビルドと検証を経てRouterをGreenへ切り替える標準フローです。dbtのdeferとstateを使うことで、未変更モデルを既存(Blue)から解決し、変更箇所のみGreenに構築します。

本番切替は、RouterスキーマのビューをGreenを参照する形に再作成して完了です。問題があれば、同じ手順でBlueを参照するように戻します。

  • 1. 差分ビルド(候補環境): dbt build --target green --defer --state path/to/prod/artifacts --select state:modified+
  • 2. テストと検証: dbt test --target green(スキーマテスト、関数テスト、カスタム検証)
  • 3. スモーククエリ・ダッシュボード確認(読み取り先をRouterに固定したまま実施)
  • 4. 切替(パブリッシュ): dbt run-operation publish_router --args '{"color": "green"}'
  • 5. 監視(クエリ失敗、レイテンシ、指標乖離)
  • 6. 不具合時のロールバック: dbt run-operation publish_router --args '{"color": "blue"}'

実装例: profilesとマクロでスキーマ切替を自動化

2つのtargetを用意し、Blue/Greenのスキーマを固定名で割り当てます。切替はrun-operationでRouterスキーマのビューを一括で作り直します。selectorsはstate:modified+を使い、deferで未変更部分を現行に解決します。

以下は最小構成の例です。実環境では権限付与(GRANT USAGE/SELECT)や、モデルごとの例外対応、非同期監視などを追加してください。

  • profiles.ymlでblue/greenのoutputsを分ける
  • publish_routerマクロでRouterスキーマのビューを再作成
  • CIではdbt build --target green --defer --state ... --select state:modified+ を推奨

profiles.yml と publish_router マクロの例

# profiles.yml(抜粋)
my_project:
  target: blue
  outputs:
    blue:
      type: snowflake  # 例。BigQuery/Databricks等でも同様にtargetでスキーマ分離
      account: <account>
      user: <user>
      password: <password>
      role: <role>
      database: ANALYTICS
      warehouse: TRANSFORMING
      schema: analytics_blue
    green:
      type: snowflake
      account: <account>
      user: <user>
      password: <password>
      role: <role>
      database: ANALYTICS
      warehouse: TRANSFORMING
      schema: analytics_green

-- macros/publish_router.sql
{% macro publish_router(color='green', router_schema='analytics', models=None) %}
  {# colorは'blue'または'green' #}
  {% set db = target.database %}
  {% set base_schema = 'analytics_' ~ color %}

  {# 対象モデルの解決 #}
  {% if models is not none %}
    {% set selected = [] %}
    {% for m in models %}
      {% do selected.append(graph.nodes['model.' ~ project_name ~ '.' ~ m]) %}
    {% endfor %}
  {% else %}
    {% set selected = graph.nodes.values() | selectattr('resource_type', 'equalto', 'model') | list %}
  {% endif %}

  {# ビューの再作成(単体オブジェクトは原子的に置換) #}
  {% for node in selected %}
    {% set src = adapter.quote(db) ~ '.' ~ adapter.quote(base_schema) ~ '.' ~ adapter.quote(node.alias) %}
    {% set dst = adapter.quote(db) ~ '.' ~ adapter.quote(router_schema) ~ '.' ~ adapter.quote(node.alias) %}
    {% do run_query('create or replace view ' ~ dst ~ ' as select * from ' ~ src) %}
  {% endfor %}
{% endmacro %}

# selectors.yml(差分ビルド用の例)
selectors:
  - name: ci_modified
    definition:
      union:
        - method: state
          value: modified+
          children: true
        - method: fqn
          value: "tests"

検証・ロールバック・運用の勘所

検証はモデル単体テストに加えて、指標整合性(例: 前日比の乖離)、件数・主キー重複、重要テーブル間の行数・合計値差分などを含めると失敗の早期検知につながります。Routerの切替直後は監視を厚くし、5〜15分を重点観測とします。

ロールバックはpublish_routerをBlueに向けて再実行するだけで即時完了します。実体スキーマの中身はそのまま保持されるため、原因調査をしつつGreenを再ビルドできます。一定期間後に古いスキーマをクリーンアップする運用(タグやメタデータ管理)を合わせて設計します。

  • 最低限のスモーク: レコード件数、主キー重複、NULL率、主要指標の差分
  • 監視: クエリエラー、スロークエリ、BIダッシュボードの読み込み失敗率
  • クリーンアップ: 直近N世代を残し、それ以前のBlue/Greenを削除(スケジュール化)

試験対策: 倉庫別の考慮点とよくある誤解

Analytics Engineer試験では、環境の分離、差分ビルド(state:modified+)、deferの意味、ロールバック戦略が頻出です。Blue/Green文脈では、ビューの置換が一般に原子的である一方、複数オブジェクトを完全同時に切替できるかはエンジン依存である点を押さえます。

主要クラウドDWHの安定的な挙動を比較します。ここでのポイントは、ポータブルに運用したいならRouterビュー方式が共通解になりやすいことです。

  • deferは未変更依存を既存環境で解決しつつ、変更分だけを候補環境に構築するために使う
  • state:modified+は変更ノードとその下流を選択。--stateには直近の本番アーティファクトを指定
  • ロールバックはスキーマ破壊ではなく参照先の再公開で行うのが安全
機能/性質SnowflakeBigQueryDatabricks (Delta)
ビューのCREATE OR REPLACE原子的置換(メタデータ更新)。一般的に短時間原子的置換。メタデータ操作が高速原子的置換。メタデータ更新で切替
スキーマ(データセット)スワップスキーマのSWAPは不可(DB間SWAPやテーブルSWAPは提供)データセットのスワップ不可スキーマスワップ不可
テーブルの原子的入替ALTER TABLE ... SWAP WITHが利用可能CREATE OR REPLACE TABLE / スナップショット・コピーで対応CREATE OR REPLACE TABLE(Deltaのトランザクションで原子的)
クローン/タイムトラベルゼロコピーCLONEで迅速復旧可テーブルスナップショットで復旧可DeltaのTime Travelで復旧可
権限の引き継ぎビューに対するGRANTは独立。再作成時のGRANT維持に注意ビュー再作成で権限再付与必要な場合ありビュー再作成時の権限維持に注意(スクリプト化推奨)

問題で確認

Analytics Engineer

問題 1

dbtでBlue/Greenデプロイを実装しています。現行はanalytics_blue、候補はanalytics_greenで、利用者はanalyticsスキーマを参照します。変更されたモデルのみを候補にビルドし、テスト合格後にダウンタイムなく切替・即時ロールバック可能にしたい。最も適切な手順はどれですか?

  1. state:modified+と--deferでanalytics_greenにdbt buildし、テスト合格後にpublish_routerマクロでanalytics内のビューをgreen参照にCREATE OR REPLACEする。問題時は同マクロでblue参照に戻す。
  2. analyticsスキーマ内のテーブルを直接CREATE OR REPLACEし、問題時は同テーブルをDROPして再作成する。
  3. analytics_blueのテーブルをすべてRENAMEしてanalyticsに上書きし、問題時はRENAMEを元に戻す。
  4. dbt seedで全データを再投入し、問題があればdbt cleanで削除してやり直す。

正解: A

変更のみを候補スキーマに構築するにはstate:modified+と--deferが有効で、切替はRouterスキーマ(analytics)のビューをCREATE OR REPLACEで再公開するのがダウンタイムを最小化します。問題時は参照先をBlueに戻すだけで即時復旧できます。

よくある質問

権限(GRANT)は切替のたびにやり直す必要がありますか?

Routerスキーマ配下のビューに対するGRANTを固定化すれば、切替時はビューの中身(参照先)だけを置換するため、通常は追加の権限作業は不要です。ただしDWHによってはCREATE OR REPLACEで権限が外れる場合があるため、ビュー再作成後に権限検証・再付与を自動化するのが安全です。

完全な同時切替(全ビューを同一瞬間に切替)は可能ですか?

単一ビューの置換は原子的ですが、複数オブジェクトを絶対同時に入れ替えるかはエンジン機能に依存します。多くの現場ではスキーマ互換性を維持しつつ、短時間の逐次置換と監視で十分な可用性を確保します。厳密な同時性が要件なら、エンジン固有のスワップ機能や発行順制御を検討します。

--deferとstate:modified+は本番でも安全に使えますか?

はい。--stateに直近の本番アーティファクト(manifest.json/runner_artifacts)を指定し、--deferで未変更の上流を本番から解決すれば、変更分だけを候補に再構築できます。実体を破壊せずに差分ビルドできるため、Blue/Greenと相性が良いです。

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

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の記事一覧 (101件)
© 2026 NicheeLab All rights reserved.