DEA / ドメイン2 データストア管理
スキーマの進化とデータ特性の変化
データパイプラインは、作った時点の前提のまま動き続けるわけではありません。上流のアプリが列を足したり型を変えたりし (スキーマの進化)、データの量や値の分布も変わります (データ特性の変化)。DEA-C01 では、こうした変化に対処する方法 (スキル 2.4.2) として、の更新動作、 のスキーマの扱い、 のスキーマ進化、 の互換性モード、データ量や分布の変化への対応が問われます。
Point
- スキーマの進化 (schema evolution): 時間とともにスキーマ (列と型) が変わることと、それに安全に追従する仕組みです。
- 後方互換 (backward compatible): 新しいスキーマで、古いスキーマのデータを読めることです。
- 前方互換 (forward compatible): 古いスキーマで、新しいスキーマのデータを読めることです。
- 和訳
- Evolution: 進化、発展
- Weblio英和辞書「evolution」
概要
| 変化 | 例 | 起きやすい問題 |
|---|---|---|
| 列の追加 | 注文に「クーポンコード」が増える | 古いテーブル定義に列がなく、値が読まれない |
| 列の削除 | 使わなくなった列が消える | 下流のジョブが列を参照して失敗する |
| 列の名前変更 | cust_id → customer_id | 名前で読む形式では別の列と扱われる |
| 型の変更 | 整数 → 文字列、int → bigint | 型が合わずクエリやジョブが失敗する。同じ列に型が混在する |
| データ量の増加 | 1日 10 GB → 1 TB | ジョブの時間切れ、メモリ不足、費用の急増 |
| 分布の変化 | 特定の顧客にデータが集中する | 、ホットパーティション |
試験では、「上流の変更でパイプラインを止めない」「本番のテーブル定義を壊さない」「互換性のない変更を事前に止める」といった要件から手段を選びます。
主要技術
①クローラーとカタログの更新動作
は、スキーマ変更ポリシーに従ってカタログのテーブル定義を変えます (「 Data Catalog とクローラー」の章)。
| 方針 | 動作 | 向くケース |
|---|---|---|
| テーブル定義を更新する | 列の追加・型の変更をカタログへ反映する | 上流の変更にすぐ追従したい |
| 新しい列だけを追加する | 既存の列は変えず、増えた列だけを足す | 既存の列の型を勝手に変えられたくない |
| 更新しない (ログのみ) | 変更を記録するだけ | 本番の定義を人が確認してから変えたい |
Glue ジョブが書き込み時にカタログを更新する場合は、enableUpdateCatalog と更新動作 (updateBehavior) を指定して、新しい列やパーティションを反映させます。
②ファイル形式とスキーマの読み方 ⚠️ 頻出
| 形式 | 列の対応のさせ方 | 変化への強さ |
|---|---|---|
| CSV | 位置 (何番目の列か) | 途中に列が挿入されると、それ以降の列がずれる。列は末尾に追加するのが原則 |
| 名前 | 列の追加に強い。型の揺れ (数値と文字列の混在) が起きやすい | |
| 名前 ( の既定) | 列の追加・削除に強い。名前の変更は別の列になる | |
| スキーマを一緒に持ち、互換性の規則で解決 | 既定値つきの列の追加などに強い。 と相性がよい |
の は、同じ列に複数の型が混ざっていても読み込めるよう、型の候補を「選択肢 (choice)」として持ちます。resolveChoice で、型をそろえる (cast)、型ごとに別の列に分ける (make_cols)、構造体にする (make_struct)、片方の型だけを残す (project) を選べます。
③Apache Iceberg のスキーマ進化
は、列を名前ではなく内部の ID で管理します。そのため、データファイルを書き直さずに、メタデータの変更だけで安全にスキーマを変えられます。
| 操作 | Iceberg での扱い |
|---|---|
| 列の追加 | 既存のファイルにはない列として null で読まれる |
| 列の削除 | メタデータから外す。同じ名前で新しい列を足しても、古いデータと混ざらない |
| 名前の変更 | ID が同じなので、過去のデータもそのまま新しい名前で読める |
| 型の拡大 | int → bigint、float → double など、安全な拡大ができる |
| 列の並べ替え | 読み取りに影響しない |
| パーティションの進化 | 粒度を変えても既存データは書き直さない |
では ALTER TABLE ... ADD COLUMNS、CHANGE COLUMN などで変更します。通常の のテーブルで名前を変えると過去のデータの列が読めなくなる問題を、Iceberg なら避けられます (「と 」の章)。
④AWS Glue Schema Registry ⚠️ 頻出
ストリーミングでは、プロデューサー (送る側) とコンシューマー (読む側) が別のチームのことが多く、勝手なスキーマ変更がコンシューマーを壊します。 は、スキーマを一元的に登録し、新しい版を登録するときに互換性を検査します。
| 項目 | 内容 |
|---|---|
| 対応形式 | 、 Schema、Protocol Buffers (Protobuf) |
| 連携先 | / 、、、 |
| 費用 | 無料 () |
| 仕組み | プロデューサーのシリアライザーがスキーマを登録・参照し、コンシューマーのデシリアライザーが同じスキーマで読む |
| 互換性モード | 意味 | 許される変更の例 |
|---|---|---|
| BACKWARD (推奨) | 新しいスキーマのコンシューマーが、直前の版のデータを読める | 列の削除、任意 (optional) の列の追加 |
| BACKWARD_ALL | 新しいスキーマで、過去のすべての版のデータを読める | 同上 (すべての版に対して検査) |
| FORWARD | 直前の版のコンシューマーが、新しいスキーマのデータを読める | 列の追加、任意の列の削除 |
| FORWARD_ALL | 過去のすべての版のコンシューマーが新しいデータを読める | 同上 (すべての版に対して検査) |
| FULL | 直前の版と前後どちらにも互換 | 任意の列の追加・削除 |
| FULL_ALL | すべての版と前後どちらにも互換 | 同上 |
| NONE | 検査しない | 何でも登録できる (開発時) |
| DISABLED | 新しい版を登録させない | スキーマを固定する |
Point
- BACKWARD = 「新しいコンシューマーが古いデータを読める」→ コンシューマーを先に更新するときに使います。
- FORWARD = 「古いコンシューマーが新しいデータを読める」→ プロデューサーを先に更新するときに使います。
- FULL = 両方。どちらを先に更新してもよい。
- 必須の列を追加すると、古いデータにその列がないため BACKWARD では登録できません。任意 (既定値つき) の列なら登録できます。
⑤データ特性の変化への対処
スキーマが同じでも、データの量や分布が変わるとパイプラインは壊れます。
| 変化 | 症状 | 対処 |
|---|---|---|
| 量の増加 | ジョブの時間切れ、メモリ不足 | ワーカーの数・種類を増やす、オートスケーリング、パーティションでの分割処理、ブックマークで増分だけ処理 |
| 量の急増 (一時的) | 、遅延 | やの容量 ( オンデマンド、 Serverless、 オンデマンド) |
| 分布の偏り | 一部のタスクだけ長い、ホットパーティション | の見直し、、Redshift のの見直し |
| 値の種類の増加 | パーティションが膨大になる | パーティションの粒度を粗くする、化 |
| 値そのものの変化 () | 平均や件数が急に変わる、範囲外の値 | のルールとで検出して止める・通知する (「データ品質の確保」の章) |
| 遅れて届くデータ | 過去の日付のパーティションに後から追加される | 再処理の対象期間を決める、 の で取り込む |
試験対策
①判断マトリクス
| 問題文のキーワード | 選ぶもの |
|---|---|
| 上流の列の追加をカタログに自動で反映 | の「テーブル定義を更新する」、 ジョブの enableUpdateCatalog |
| 本番のテーブル定義を勝手に変えさせない | クローラーの「更新しない (ログのみ)」または「新しい列だけを追加」 |
| 同じ列に数値と文字列が混在してジョブが失敗 | の resolveChoice |
| 列の名前変更・型の拡大をデータの書き直しなしで | のスキーマ進化 |
| ストリームのスキーマ変更でコンシューマーを壊さない | の互換性モード |
| コンシューマーを先に更新する | BACKWARD |
| プロデューサーを先に更新する | FORWARD |
| CSV に列を追加したい | 末尾に追加する (位置で読まれるため) |
| データ量の増加でジョブが時間切れ | ワーカーの増強、オートスケーリング、増分処理 |
| 値の分布の急な変化を検出 | の |
②よくある誤答
- CSV の途中に列を挿入すること。位置で読まれるため、以降の列の値がずれます。
- のテーブルで列名を変えれば、過去のデータも新しい名前で読めると考えること。名前で対応させるため、別の列として扱われます。 を使います。
- の互換性モードを NONE のまま本番で使うこと。互換性のない変更が通ってしまいます。
- BACKWARD 互換で、必須の列を追加できると考えること。古いデータに値がないため登録できません。