「営業システム側が機能追加で `notes` カラム追加しました」── 開発側にとっては小さな変更が、データ基盤側にはカスケード障害を引き起こす。スキーマドリフトは静かに進行し、ある日突然 が失敗します。
あの時こうすれば良かった、と思う症状
・営業から「先週から数字が変です」 / ・ETL ログに `column not found` / ・突然 NULL 比率が増えた / ・「列の意味が変わったらしい」(ID が再利用された等)
起きる仕組み(よくあるパターン)
- カラム追加:ソース側で気軽に追加。SELECT * で取ってると問題なし、明示列で取ってると古い ETL でも動く(が新カラムは取れない)
- カラム削除:明示参照していた場所が即死
- 型変更:`int → string` 等で JOIN や集計が壊れる(特にゼロパディング `001` を削った瞬間)
- 意味の変更:`status: 1 = 進行中` だったのが `1 = 完了` に逆転
- 主キーの再利用:削除されたユーザID が新規ユーザに再付与される
調査手順
bigquery:直近の INSERT カラム数の変化を見る
SQL
-- ソース → ステージングテーブルの行数・NULL率の異常検知SELECT DATE(loaded_at) AS day, COUNT(*) AS rows, COUNTIF(notes IS NULL) / COUNT(*) AS null_ratio_notes, COUNTIF(status_v2 IS NULL) / COUNT(*) AS null_ratio_status_v2FROM staging.ordersWHERE loaded_at > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)GROUP BY dayORDER BY day DESC;- INFORMATION_SCHEMA.COLUMNS の差分:1週間ごとのカラム一覧を保存して diff
- dbt schema test:`unique`/`not_null`/`accepted_values` で型・値の前提が崩れていないか毎晩
- Great Expectations / Soda:データ品質ルールで「列の存在」「型」「分布」を継続検査
- ソース側のリリースノート:開発チームに「列追加したら notify ください」を文化化
短期対処
- SELECT * を一時的に避難:明示列指定で「想定列だけ取る」に切り替え
- 型キャスト追加:`SAFE_CAST` で fail を NULL に
- dbt の `column_types`:型強制で予期せぬ拡張を検知
- バックアップから復元:壊れる前のデータで再ロード
中長期対策
- Schema Registry(Confluent / Avro):ソース側がスキーマを宣言、互換性違反は で止める
- 自動カラム追加 + alert:スキーマドリフトを検知したらカラム自動追加 + 通知
- DataHub / OpenMetadata:データカタログでカラムの意味を管理し、属人化を解消
- 契約テスト(Data Contract):ソース側と分析側の「合意」を yaml で明文化
- lint ルール:`SELECT *` 禁止(前章でも触れた、スキーマドリフトと相性悪し)
ふくふくの進め方
ソース・ステージング・marts の全テーブルに schema test + freshness test を1週間で当てる、というのが入りの提案です。1ヶ月後にはスキーマドリフト由来の障害は半減以下が目安。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。