モデリングの寿命はスキーマ変化への耐性で決まります。dbt には、増分モデルの列追加・削除が発生した際の動きを制御する on_schema_change という重要な設定があります。
本稿では、各オプションの意味と選び方、主要データウェアハウスでの注意点、試験で狙われやすい論点を、現場の観点で解説します。
on_schema_change は、dbt の増分モデルでターゲットテーブルとモデルの列集合が食い違ったときの挙動を決めるモデル設定です。検知対象は「列の追加・削除」です。型変更は基本的に対象外で、DDL が必要な場合は別途対応します。
適用範囲は増分マテリアライズのみです。table や view、ephemeral には効きません。検知は、ターゲットリレーションの実際の列と、コンパイル後モデルの列リストを突き合わせることで行われます。
最小設定例:モデル内で on_schema_change を指定
{{
config(
materialized='incremental',
incremental_strategy='merge',
unique_key='id',
on_schema_change='append_new_columns'
)
}}
select
id,
event_time,
value,
-- 将来ここに新規列が増える想定
from {{ ref('stg_events') }}on_schema_change の主な選択肢は ignore, fail, append_new_columns, sync_all_columns の4つです。違いは、新規列の取り込みと既存列の削除を自動で行うか、検知時にビルドを止めるか、に集約されます。
安全側に倒すなら fail、継続性を重視して新規列のみ受け入れるなら append_new_columns、モデル定義を常に真実としたいなら sync_all_columns が実務での定番です。
| オプション | 新規列の扱い | 削除列の扱い | 型変更の扱い |
|---|---|---|---|
| ignore | 無視(既存列のみでDML) | 無視(ターゲットに残存) | 対象外(多くは未対応) |
| fail | 検知時にエラーで停止 | 検知時にエラーで停止 | 対象外(型差異は別途) |
| append_new_columns | ALTER TABLE で追加 | 無視(ドロップしない) | 対象外(別対応) |
| sync_all_columns | 追加する | 削除する(倉庫依存) | 対象外(別対応) |
プロジェクト既定として指定(dbt_project.yml)
models:
marts:
+materialized: incremental
+incremental_strategy: merge
+on_schema_change: sync_all_columnsSnowflake は ALTER TABLE の ADD/DROP COLUMN が安定しており、append_new_columns も sync_all_columns も実務で使いやすい構成です。列削除は依存オブジェクトがないことが前提です。
BigQuery は ADD/DROP COLUMN をサポートします。増分戦略が merge の場合は on_schema_change が働きますが、insert_overwrite を使う場合はテーブル再作成を伴わないため期待通りにならないことがあります。必要に応じ full_refresh を併用します。
Databricks(Delta Lake)は列追加に強く、列削除はランタイムやテーブル特性に依存します。sync_all_columns での削除は事前検証を推奨します。いずれも merge 戦略と相性が良いです。
ターゲット別に挙動を切り替えるヒント(環境変数を併用)
models:
+on_schema_change: '{{ env_var("DBT_ON_SCHEMA_CHANGE", "ignore") }}'
# 実行時に上書き例
# DBT_ON_SCHEMA_CHANGE=sync_all_columns dbt run -s dim_customeron_schema_change の効果は、戦略がテーブル定義を維持したまま DML を流す場合に現れます。典型は merge 戦略です。ignore のときは、ターゲットに存在しない列を除外して DML を生成するため、ビルドは成功しますが新規列は取り込まれません。
insert_overwrite(特に BigQuery)では、分割領域の置換で完結するため、on_schema_change の列追加・削除ロジックが期待通りに適用されないケースがあります。スキーマ変更を確実に反映したい場合は full_refresh と併用するのが安全です。
増分ビルド時のスキーマ差分ハンドリング フロー
merge 戦略での典型モデル
{{
config(
materialized='incremental',
incremental_strategy='merge',
unique_key='order_id',
on_schema_change='sync_all_columns'
)
}}
select
order_id,
customer_id,
total_amount,
updated_at
from {{ ref('stg_orders') }}新規列の段階的導入は append_new_columns を既定にし、数サイクル後に sync_all_columns へ切り替えると影響範囲を抑えられます。列削除は影響調査と依存オブジェクトの洗い出しを済ませてから同期を有効化します。
失敗時の復旧は、まず fail で停止させ、テーブルバックアップを確認、必要なら --full-refresh で再作成し、以降の増分に戻します。変更は dbt のログに残るため、監査には run_results.json と invocation_id を活用します。
代表的な運用コマンド
# ふつうの増分ビルド
dbt run -s fact_sales
# 強制的に作り直してスキーマを確実に適用
dbt run --full-refresh -s fact_sales
# 失敗時のトラブルシュート用にデバッグ
dbt debug && dbt ls -s fact_sales && dbt compile -s fact_salesAnalytics Engineer 試験では、on_schema_change の既定値、各オプションの違い、いつ full_refresh が必要か、戦略ごとの適用可否が狙われます。型変更が対象外である点や、view には効かない点もチェックポイントです。
モデル契約(contract enforced: true)を使うと、列の過不足でビルドが失敗します。on_schema_change は DDL の自動適用、contract はスキーマ逸脱の禁止という役割分担で、組み合わせると強固なガバナンスになります。
モデル契約の例(列逸脱で失敗)
models:
- name: dim_customer
config:
contract:
enforced: true
materialized: incremental
incremental_strategy: merge
on_schema_change: fail
columns:
- name: customer_id
data_type: string
- name: customer_name
data_type: stringAnalytics Engineer
問題 1
増分モデル(strategy=merge)で upstream に新規列が追加された。運用を止めずに新規列も取り込みたいが、既存列の削除はまだ行いたくない。適切な on_schema_change の設定はどれか。
正解: A
append_new_columns は新規列のみ ALTER TABLE で追加し、削除は行いません。ビルドは続行し、過去行の新規列は NULL で埋まるのが一般的です。sync_all_columns は削除も行う可能性があるため要件と不一致、ignore は新規列を取り込みません。fail は検知で停止します。
on_schema_change は型変更(STRING→INT など)も自動で適用するか?
いいえ。対象は列の追加・削除です。型変更は倉庫固有の制約が大きく、dbt は自動変換しません。別途 ALTER COLUMN や full_refresh を計画します。
view や table マテリアライズにも on_schema_change は効くか?
いいえ。on_schema_change は増分マテリアライズ向けの設定です。view は再作成で常に最新スキーマを反映、table は再作成や full_refresh で対応します。
デフォルトの ignore で新規列を参照する SQL に変えたらビルドは失敗する?
通常は失敗しません。dbt はターゲットに存在しない列を除外して DML を生成します。ただし新規列は取り込まれません。取り込みたい場合は append_new_columns か sync_all_columns を使います。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
dbt Model の基礎: SQL で定義する変換の最小単位
Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...
dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点
dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...
dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点
dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...
dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト
Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....
dbt_project.yml の読み方:主要設定と命名を最短で掴む
dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...