ソースシステム側が「ちょっとカラムを追加しただけ」の軽い気持ちでスキーマを変更した翌朝、データ基盤のパイプラインが赤く燃え、下流のBIダッシュボードが空白になる――この痛みを経験したデータエンジニアは決して少なくありません。スキーマ進化(Schema Evolution)の設計は、こうした「静かなAPI破壊」を防ぐための技術です。本記事では、後方互換性の考え方から、dbt contractsやApache Icebergのスキーマ進化機能まで、破壊的変更を未然に防ぐ実装パターンを解説します。
スキーマ進化とは何か――「カラム追加でパイプラインが壊れる」問題
スキーマ進化とは、データのスキーマ(テーブル定義)が時間とともに変化することに、パイプラインとストレージを追従させる設計の考え方です。ソースシステムの新機能追加、ビジネス要件の変化、バグ修正――あらゆる理由でスキーマは変わり続けます。問題は、ソースの1箇所の変更が、DWHとBI全体に波及することです。
特に危険なのが「SELECT *で受けているパイプライン」です。ソース側で順序が変わった、型が変わった、カラムが消えた――このいずれかが起きた瞬間、取り込みジョブは失敗するか、もっと悪い場合は「成功したように見えて値が入れ替わっている」という恐ろしい事象を引き起こします。スキーマ進化の設計とは、こうした変更を検知し、互換性を保ったまま進化させる仕組みのことです。データコントラクトとの併用で、より強固な防御が可能になります。
スキーマ変更の分類
スキーマ変更は「互換性」の観点で3種類に分類できます。後方互換(Backward Compatible)は、新スキーマで古いデータを読める変更、前方互換(Forward Compatible)は古いスキーマで新データを読める変更、そして両方満たさない破壊的変更(Breaking Change)です。この分類を押さえておけば、レビュー時に「これは受け入れていいか」の判断が機械的にできるようになります。
| 変更種別 | 具体例 | 下流影響 | 対応必要度 |
|---|---|---|---|
| 後方互換(安全) | nullableなカラム追加、enumの値追加 | ほぼなし | 低 |
| 前方互換(条件付安全) | optionalなフィールド削除 | 古い読み手は無視 | 中 |
| 破壊的変更(危険) | カラム削除、型変更、NOT NULL追加 | パイプライン全破壊 | 高 |
| リネーム | カラム名の変更 | SELECT依存コードすべて破壊 | 高 |
【スキーマ変更影響フロー】
[スキーマ変更申請]
|
v
変更種別の判定
├── 後方互換 --> そのまま適用OK
├── 前方互換 --> 下流読み手の確認後に適用
└── 破壊的 --> バージョニング必須
|
v
[v2エンドポイント作成]
|
v
[移行期間(2〜4週間)]
|
v
[v1廃止]
破壊的変更を防ぐ設計パターン
破壊的変更を防ぐ最も効果的なパターンは、スキーマを「契約(Contract)」として明示的に定義することです。dbt contractsを使えば、モデルの出力スキーマをYAMLで宣言的に定義し、ビルド時に型やNOT NULL制約をチェックできます。PR時点で破壊的変更を検知し、マージ前にブロックできるのが最大のメリットです。
# models/marts/_marts.yml
version: 2
models:
- name: dim_customers
config:
contract:
enforced: true
columns:
- name: customer_id
data_type: string
constraints:
- type: not_null
- type: primary_key
- name: email
data_type: string
ストレージ層では、Apache Icebergのスキーマ進化機能が強力です。Icebergは内部的にカラムをIDで管理しているため、カラム名のリネームや順序変更が安全に行えます。Hiveテーブルで悩ましかった「カラム追加で過去データが崩れる」問題が起きません。オープンテーブルフォーマットの比較記事も合わせてご覧ください。
-- Icebergのスキーマ進化SQL例
ALTER TABLE prod.db.orders ADD COLUMN promo_code STRING;
ALTER TABLE prod.db.orders RENAME COLUMN amount TO total_amount;
ALTER TABLE prod.db.orders DROP COLUMN legacy_flag;
スキーマ変更の運用プロセス
技術だけでなく、運用プロセスとしてスキーマ変更を管理することも重要です。変更申請→影響分析→レビュー→テスト→本番適用→モニタリングの6ステップを定義し、CI/CDパイプラインに組み込みます。
| フェーズ | 作業内容 | 担当 | ツール例 |
|---|---|---|---|
| 申請 | PR作成・変更理由の明記 | ソース側開発者 | GitHub/GitLab |
| 影響分析 | リネージで下流依存を洗い出し | データエンジニア | dbt docs、DataHub |
| レビュー | 互換性種別の判定 | データチームリード | コードレビュー |
| テスト | 契約チェック・品質テスト | CI | dbt contract、Great Expectations |
| 本番適用 | 段階的ロールアウト | オペレーター | Airflow、GitHub Actions |
| モニタリング | 鮮度・件数変動の監視 | SRE/オンコール | Elementary、Monte Carlo |
特に「影響分析」フェーズは省略されがちですが、下流に50本のdbtモデルがぶら下がっているテーブルを破壊的に変更するリスクは甚大です。リネージツールで依存を可視化し、影響を受ける全モデルのオーナーに事前通知する仕組みを持ちましょう。
ツール別のスキーマ進化対応
DWHとテーブルフォーマットによってスキーマ進化への対応度は大きく異なります。新規構築であれば、Iceberg/Delta Lakeなどのオープンテーブルフォーマットを採用することで、破壊的変更のリスクを大幅に下げられます。
| 製品 | カラム追加 | リネーム | 型変更 | 備考 |
|---|---|---|---|---|
| Snowflake | 可 | 可(ALTER) | 一部のみ可 | 型変更は安全な方向のみ |
| BigQuery | 可 | 可 | REQUIREDからNULLABLEのみ | ALTER TABLE DROP COLUMNは2022以降 |
| Redshift | 可 | 可 | 制限的 | 大規模テーブルでコスト増 |
| Apache Iceberg | 可(安全) | 可(ID管理) | 可(昇格) | カラムID管理で最強 |
| Delta Lake | 可 | 可 | 一部可 | mergeSchemaオプション |
| Hive(標準) | 可 | 危険 | 不可 | 位置ベースで破損しやすい |
ベストプラクティス5選
スキーマ進化の運用で実効性の高いベストプラクティスを5つ紹介します。第一に、SELECT *の禁止です。明示的にカラムを指定することで、未知のカラム追加で処理が予期せず変わるリスクを排除できます。dbt stagingモデルでも、カラムを全て書き出すのが理想です。
第二に、破壊的変更は必ずバージョニングすることです。既存テーブルをv1として残し、新しいスキーマをv2として作成、移行期間を設けてから旧バージョンを廃止します。第三に、契約の強制です。dbt contractsやsoda-coreを使い、CIで自動的にスキーマを検証します。第四に、リネージの可視化です。DataHub、OpenLineage、dbt docsなどで下流依存を常に把握できる状態にしておきます。
第五に、コミュニケーション設計です。スキーマ変更はテクニカルな問題であると同時に組織的な問題でもあります。ソース側の開発チームとデータチームで定期的にスキーマレビュー会を開催し、「これから変えたい」を事前に共有する場を作るだけで、破壊的変更の9割は防げます。dbt入門と合わせて、運用プロセスの設計に取り組んでください。
まとめ
スキーマ進化の設計は、データ基盤の長期安定運用の鍵です。後方互換・前方互換・破壊的変更の3分類を理解し、dbt contractsやIcebergなどのツールで自動検証を組み込むことで、「ある朝突然パイプラインが燃える」事態を防げます。技術と運用プロセスの両面から、スキーマ変更を「管理された変化」に変えていきましょう。データパイプライン設計全体の中で位置づけることも重要です。
よくある質問(FAQ)
Q. スキーマ進化で最も注意すべき変更は?
カラムの削除と型変更が最も危険な破壊的変更です。下流のすべてのパイプラインとダッシュボードに影響するため、事前の影響分析とバージョニングによる移行期間の確保が必須です。
Q. スキーマ変更をCIで検知できますか?
はい。dbt contractsやsoda-coreのスキーマチェックをCI/CDに組み込むことで、マージ前に破壊的変更を検知できます。PRレビュー時点で自動的に互換性が検証されるため、運用負荷を下げられます。
Q. Apache Icebergのスキーマ進化はどう機能しますか?
IcebergはカラムID管理によりカラム名の変更・追加・削除を安全に行えます。カラム名ではなく内部IDで追跡するため、リネーム時もデータの整合性が保たれ、過去データを読む際にも問題が発生しません。