Databricks Certified Data Engineer Associate 教科書
第1章 Databricks Intelligence Platform(6%)
🎯 この節の学習目標
Delta Lake は、クラウドオブジェクトストレージ上のデータレイクに DWH 並みの信頼性を与えるオープンなストレージフォーマットです。その実体は驚くほどシンプルで、次の2つの要素でできています。
| 要素 | 実体 | 役割 |
|---|---|---|
| データファイル | Parquet 形式のファイル群 | テーブルデータの実体。列指向で圧縮効率・読み取り効率が高い |
| トランザクションログ | _delta_log ディレクトリ内の JSON ファイル(+チェックポイント) | 「どのファイルがテーブルの現在の状態を構成するか」を記録する唯一の真実源。すべての変更が順序付きのコミットとして追記される |
テーブルへの書き込みは「新しい Parquet ファイルを追加し、その事実を _delta_log にコミットとして記録する」という形で行われます。読み取り側は必ずログを起点に「現在有効なファイル一覧」を解決するため、書き込み途中の中途半端な状態が読み手に見えることはありません。この仕組みがオープンな標準として公開されているため、Databricks 以外のエンジンからも同じテーブルを読み書きできます。
トランザクションログがあることで、Delta Lake は ACID 特性を保証します。
| 特性 | 意味 | Delta Lake での実現 |
|---|---|---|
| A:原子性(Atomicity) | 変更は「全部成功」か「全部なかったこと」のどちらか | ログへのコミットが成立して初めて変更が可視化される。途中失敗はコミットされず、読み手には見えない |
| C:一貫性(Consistency) | テーブルは常に整合した状態を保つ | スキーマ強制(後述)や制約により不正なデータの混入を防ぐ |
| I:分離性(Isolation) | 同時実行される操作が互いを壊さない | 楽観的同時実行制御。読み手はスナップショットを読み、書き手同士の衝突はコミット時に検出される |
| D:永続性(Durability) | コミットされた変更は失われない | ログとデータはクラウドオブジェクトストレージに永続化される |
実務的に重要なのは、「ETL ジョブがテーブルへ書き込んでいる最中でも、BI ユーザーは直前のコミット時点の一貫したスナップショットを安全に読める」という点です。素の Parquet ファイル群を直接置き換える運用では、この保証がありませんでした。
すべての変更がログにバージョン付きで残るため、Delta Lake では過去の任意時点のテーブルを読み出す(タイムトラベル)ことができます。
-- バージョン番号で過去の状態を読む
SELECT * FROM main.sales.orders VERSION AS OF 12;
-- タイムスタンプで過去の状態を読む
SELECT * FROM main.sales.orders TIMESTAMP AS OF '2026-08-01T00:00:00';
-- 変更履歴(いつ・誰が・どんな操作をしたか)を確認する
DESCRIBE HISTORY main.sales.orders;
-- 誤った更新をなかったことにして、テーブルを過去バージョンに戻す
RESTORE TABLE main.sales.orders TO VERSION AS OF 12;
VERSION AS OF / TIMESTAMP AS OF — 過去のスナップショットを読み取る(テーブル自体は変わらない)。誤更新前後の比較や再現性のある分析に使うDESCRIBE HISTORY — バージョンごとの操作・実行者・タイムスタンプの一覧。監査証跡として機能するRESTORE TABLE — テーブルの現在の状態を過去バージョンの内容に戻す(この操作自体も新しいコミットとして記録される)📝 試験のポイント
公式サンプル問題に対応する典型パターンとして、「信頼できるロールバック・監査証跡・単一の真実源(single source of truth)が必要」という要件が示されたら、正解は Delta Lake(タイムトラベル・DESCRIBE HISTORY・トランザクションログ)+ Unity Catalog(アクセス制御・監査・リネージ) の組み合わせです。生の Parquet や CSV にはバージョン管理も監査ログもない点が誤答側の根拠になります。また「過去を読むだけなら AS OF、テーブルを実際に戻すなら RESTORE」という使い分けも問われやすい論点です。
Delta Lake はテーブルのスキーマをログに保持し、書き込み時に検証します。
mergeSchema で、新しい列をテーブル定義に追加しながら書き込めます。💡 具体例:スキーマ強制に阻まれた書き込みを、スキーマ進化で通す
# PySpark:ソースに新列 coupon_code が増えたケース
df = spark.read.table("main.staging.new_orders")
# 既定ではスキーマ不一致でエラーになる(スキーマ強制)
# df.write.mode("append").saveAsTable("main.sales.orders")
# => AnalysisException: A schema mismatch detected ...
# 意図的な変更なら mergeSchema で列追加を許可して書き込む(スキーマ進化)
(df.write
.mode("append")
.option("mergeSchema", "true")
.saveAsTable("main.sales.orders"))
ポイントは「既定は拒否、進化は明示的なオプトイン」という設計です。SQL では ALTER TABLE ... ADD COLUMN で先に列を追加する方法もあります。うっかり型の違うデータを流し込んでテーブルを汚す事故を、既定の強制が防いでくれます。
Delta Lake のテーブルには、DWH と同様の DML(UPDATE / DELETE / MERGE)がそのまま使えます。特に MERGE INTO は「あれば更新、なければ挿入(upsert)」を1文で表現でき、増分取り込みの中心的な構文です。
-- テーブル作成(Unity Catalog 配下では既定で Delta 形式)
CREATE TABLE main.sales.orders (
order_id BIGINT,
customer_id BIGINT,
amount DOUBLE,
updated_at TIMESTAMP
);
-- upsert:order_id が一致すれば更新、なければ挿入
MERGE INTO main.sales.orders AS t
USING main.staging.new_orders AS s
ON t.order_id = s.order_id
WHEN MATCHED THEN
UPDATE SET t.amount = s.amount, t.updated_at = s.updated_at
WHEN NOT MATCHED THEN
INSERT (order_id, customer_id, amount, updated_at)
VALUES (s.order_id, s.customer_id, s.amount, s.updated_at);
また、運用が続くと小さなファイルが増えて読み取り性能が落ちるため、保守コマンドを併用します。
| コマンド | やること | 注意点 |
|---|---|---|
OPTIMIZE | 小さな Parquet ファイルを大きなファイルにまとめ直す(コンパクション)。読み取り性能を改善する | データの中身は変わらない。旧ファイルは「非参照」になるだけで即削除はされない |
VACUUM | もはや参照されていない古いデータファイルを物理削除してストレージを節約する | 保持期間(既定 7 日)より古いファイルが対象。削除した期間へのタイムトラベルはできなくなる |
ここまでの仕組みを、書き込みから読み取りまでの流れとして図にまとめます。
図:Delta Lake の書き込み・読み取りの流れ。すべての読み取りはトランザクションログを起点に解決される
✅ この節のまとめ
_delta_log トランザクションログのオープンなストレージフォーマット。ログが「現在の状態」の唯一の真実源。VERSION AS OF / TIMESTAMP AS OF、履歴確認は DESCRIBE HISTORY、実際に戻すのは RESTORE TABLE。mergeSchema などでスキーマ進化を明示的に許可する。OPTIMIZE で小ファイル統合、VACUUM で旧ファイルの物理削除(タイムトラベル可能期間が縮む点に注意)。問1. Delta Lake テーブルの物理的な構成として正しいものはどれか。
正解:B
Delta Lake=「Parquet+トランザクションログ」です。オープンなフォーマットであるため、Aの「独自形式で他エンジンから読めない」は誤りです。CはストレージがオブジェクトストレージではなくRDBという点で誤り、Dはログが JSON である点と混同させる選択肢で、データ本体は Parquet に格納されます。
問2. 昨夜の ETL ジョブの不具合で main.sales.orders に誤ったデータが書き込まれた。テーブル全体を不具合前のバージョン 42 の状態に実際に戻したい。実行すべきコマンドはどれか。
SELECT * FROM main.sales.orders VERSION AS OF 42DESCRIBE HISTORY main.sales.ordersRESTORE TABLE main.sales.orders TO VERSION AS OF 42VACUUM main.sales.orders正解:C
テーブルの状態を実際に過去バージョンへ戻すのは RESTORE TABLE です。Aは過去のスナップショットを「読むだけ」でテーブル自体は変わりません。Bは履歴の確認(どのバージョンに戻すべきかの調査)には有用ですが、それ自体は何も戻しません。Dは古い非参照ファイルを物理削除するコマンドで、むしろ実行するとその期間へのタイムトラベルができなくなるおそれがあります。
問3. Delta Lake のスキーマ強制(schema enforcement)の既定の動作として正しいものはどれか。
正解:A
既定はスキーマ強制で、不一致の書き込みはエラーとして拒否されます。Bはスキーマ進化の動作ですが、mergeSchema などで明示的に有効化した場合に限られ、既定ではありません。Cのような黙殺は起きず、事故に気づけるようエラーになります。Dは逆で、検証は書き込み時(write-time)に行われます。
問4. データガバナンス担当者から「誤操作からの信頼できるロールバック、すべての変更の監査証跡、部門横断で共有できる単一の真実源」という要件が提示された。Databricks 上で最も適切な構成はどれか。
正解:B
「ロールバック → タイムトラベル/RESTORE」「監査証跡 → トランザクションログ/DESCRIBE HISTORY と UC の監査機能」「単一の真実源 → UC 配下で一元管理された Delta テーブル」ときれいに対応します。AとCはバージョン管理・監査・同時実行の安全性がいずれも人手頼みで、信頼できるロールバックになりません。Dは複製ごとに内容が分岐し、「単一の真実源」の要件に真っ向から反します。