アプリケーションサービス本部の鎌田 (義) です。
データレイクで使用されるオープンテーブルフォーマットである Delta Lake, Apache Iceberg, Apache Hudi が提供する代表的な機能として以下があります。
- ACID トランザクション
- タイムトラベル
- スキーマ強制と進化
本稿では、 Databricks が利用する Delta Lake におけるタイムトラベル機能について掘り下げます。
タイムトラベル機能とは
Delta Lake テーブルの過去の任意の時点の状態を再構築したり、閲覧したり、復元したりできる強力な機能です。
タイムトラベルの利点
正確な監査 - テーブルに対するすべての操作(追加・削除・更新)は、最終的に相殺された場合でもトランザクションログに記録されるため、正確な監査が可能です。
過去データへのアクセス - 過去の任意の時点でのテーブルの状態を正確に再構築できます。
データの復元と回復 - 誤ってデータが削除されたり、破損したりした場合でも、タイムトラベルを使用してテーブルを以前のバージョンに復元できます。
Delta Lake の構成
Delta Lake テーブルでは以下の構成でファイルが格納されています。

Delta Lake におけるタイムトラベル機能のカギを握るのは、トランザクションログ (_delta_log
) です。
Delta Lake テーブルを作成するとトランザクションログが自動的に_delta_log
サブディレクトリ内に000000.json
が作成され、
以降の変更は000001.json
, 000002.json
といった具合で昇順で生成されます。
トランザクションログには、テーブルの元の状態から現在の状態に至るまでの詳細な手順がステップバイステップで記載されています。そのため、元のテーブルから開始し、その時点より前のコミットのみを処理することで、任意の時点のテーブルの状態を再現できます。
Diving Into Delta Lake: Unpacking The Transaction Log
Databricks でタイムトラベル機能を検証
公式チュートリアル に沿って、機能を体験してみます。
※補足
本記事では、公式チュートリアルで使用されている Kaggle の People10m データセットを利用します。
2025 年 7 月時点でダウンロードしたところ 1,000 万件ではなく、1,000 件しかデータが含まれていませんでしたが、本稿で検証する範囲では十分であるため、これを利用します。
テーブル作成
Kaggle からダウンロードしたデータセットを Volume に配置し、 以下コマンドでテーブルを作成、Volume のデータをテーブルにコピーします。
CREATE OR REPLACE TABLE main.default.people_10m ( id INT, firstName STRING, middleName STRING, lastName STRING, gender STRING, birthDate TIMESTAMP, ssn STRING, salary INT ); COPY INTO main.default.people_10m FROM '/Volumes/main/default/my-volume/export.csv' FILEFORMAT = CSV FORMAT_OPTIONS ( 'header' = 'true', 'inferSchema' = 'true' );
この時点で該当テーブルを管理しているバケットを確認してみると_delta_log/
ディレクトリと Parquet ファイルが作成されていました。
_delta_log
配下に JSON ファイルが二つ作成されていました。
Parquet ファイルにはデータの実体が格納されており、当然ですが直接ファイルの中身を確認するとデータを確認できました。
>>> df id firstName middleName lastName gender birthDate ssn salary 0 1 Pennie Carry Hirschmann F 1955-07-02 04:00:00 981-43-9345 56172 1 2 An Amira Cowper F 1992-02-08 05:00:00 978-97-8086 40203 2 3 Quyen Marlen Dome F 1970-10-11 04:00:00 957-57-8246 53417 3 4 Coralie Antonina Marshal F 1990-04-11 04:00:00 963-39-4885 94727 4 5 Terrie Wava Bonar F 1980-01-16 05:00:00 964-49-8051 79908 .. ... ... ... ... ... ... ... ... 995 996 Erika Kathlyn Hurst F 1991-01-30 05:00:00 928-46-9978 63758 996 997 Briana Rema Dziwisz F 1989-04-16 04:00:00 975-88-5431 70978 997 998 Khadijah Annabel Pauleau F 1982-12-07 05:00:00 926-28-3981 93078 998 999 Corrinne Hilda Davana F 1955-12-06 05:00:00 939-63-9947 70754 999 1000 Twyla Rosalinda Goves F 1983-10-03 04:00:00 909-50-8966 92470 [1000 rows x 8 columns]
データ追加/更新/削除
追加用のデータを作成し、people_10m テーブルにアップサート (更新または挿入) します。
CREATE OR REPLACE TEMP VIEW people_10m_updates ( id, firstName, middleName, lastName, gender, birthDate, ssn, salary ) AS VALUES (9999998, 'Billy', 'Tommie', 'Luppitt', 'M', '1992-09-17T04:00:00.000+0000', '953-38-9452', 55250), (9999999, 'Elias', 'Cyril', 'Leadbetter', 'M', '1984-05-22T04:00:00.000+0000', '906-51-2137', 48500), (10000000, 'Joshua', 'Chas', 'Broggio', 'M', '1968-07-22T04:00:00.000+0000', '988-61-6247', 90000), (20000001, 'John', '', 'Doe', 'M', '1978-01-14T04:00:00.000+0000', '345-67-8901', 55500), (20000002, 'Mary', '', 'Smith', 'F', '1982-10-29T01:00:00.000+0000', '456-78-9012', 98250), (20000003, 'Jane', '', 'Doe', 'F', '1981-06-25T04:00:00.000+0000', '567-89-0123', 89900); MERGE INTO main.default.people_10m USING people_10m_updates ON people_10m.id = people_10m_updates.id WHEN MATCHED THEN UPDATE SET * WHEN NOT MATCHED THEN INSERT *;
この時点で、カタログから履歴を確認してみるとこれまでの操作がバージョンとして保持されていることが分かります。
続いて、データ更新と削除を行います。
更新
UPDATE main.default.people_10m SET gender = 'Female' WHERE gender = 'F'; UPDATE main.default.people_10m SET gender = 'Male' WHERE gender = 'M';
削除
DELETE FROM main.default.people_10m WHERE birthDate < '1955-01-01'
改めて、ここまでのテーブルへの変更履歴を確認してみます。
DESCRIBE HISTORY main.default.people_10m
過去のバージョンを表示する (タイムトラベル)
過去のバージョンのテーブルにアクセスするには、version
指定かtimestamp
(日付 or タイムスタンプ形式の文字列) 指定でアクセスします。
SELECT * FROM main.default.people_10m VERSION AS OF 0 -- or SELECT * FROM main.default.people_10m TIMESTAMP AS OF '2025-07-22T22:33:29.000+00:00'
または、@構文を用いての検索も可能です ※タイムスタンプは yyyyMMddHHmmssSSS 形式
SELECT * FROM main.default.people_10m@v0 SELECT * FROM main.default.people_10m@20250722223329000
DELETE 前の状態のテーブルを表示してみると、アップサート後の状態である 1,006 件のレコードが表示されました。
DELETE 前の状態にテーブルを復元 (RESTORE) し、最新テーブルを参照すると 1,006 件のレコードが表示されました。
RESTORE TABLE main.default.people_10m TO VERSION AS OF 4;
データ削除について
テーブルからデータを削除しても、すぐに物理的に削除されるわけではありません。 これにより、タイムトラベルの機能でデータ変更前、及び削除前のテーブルを参照することも可能です。
テーブルの履歴を保持する期間delta.logRetentionDuration = "interval <interval>
はデフォルトで interval 30 days
です。
また、現在のテーブルバージョンで参照されなくなったデータファイルを削除するために VACUUM が使用するしきい値delta.deletedFileRetentionDuration = "interval <interval>"
はデフォルトで interval 7 days
です。
この値はテーブル作成時または ALTER TABLE にて変更可能です。
VACUUM によって削除されたデータファイルに変更または削除されたレコードが含まれている場合、以降はレコードにアクセスできなくなります。
例えば、30 日間の履歴データにアクセスしたい場合はdelta.deletedFileRetentionDuration
の値もdelta.logRetentionDuration
に合わせて 30 日に設定する必要があります。
予測的最適化
予測的最適化 が有効となっている場合 VACUUM は自動的に行われます。
予測的最適化は、テーブル管理を自動化してくれる便利な機能です。 VACUUM の他にも OPTIMIZE, ANALYZE が予測的最適化が有効なテーブルに対して自動的に実行されます。 OPTIMIZE は小さなデータファイルが多数存在する場合読み取り性能の劣化に繋がる為、大きなデータファイルに最適化してくれます。
なお、予測的最適化の実行については、ドキュメントに以下の記載があります。
予測的最適化は、 ANALYZE、 OPTIMIZE、および VACUUM 操作からメリットが得られるテーブルを特定し、サーバレス コンピュート for ジョブを使用して実行するようにキューに入れます。
Unity Catalog マネージドテーブル向け予測最適化
予測的最適化が有効化となっているかは、以下のコマンドで確認可能です。
DESCRIBE (CATALOG | SCHEMA | TABLE) EXTENDED name
また、予測的最適化が実行された履歴はsystem.storage.predictive_optimization_operations_history
テーブルから確認できます。
おわりに
本記事では、Delta Lake の代表的な機能であるタイムトラベルについて、Databricks 環境での実際の検証を通して詳しく解説しました。
タイムトラベル機能は、単なる「過去のデータを見る」機能ではありません。 トランザクションログによる正確な監査、誤操作からの迅速な復旧、データの変更履歴の追跡など、企業のデータガバナンスにおいて極めて重要な価値を提供します。
最後まで読んでいただき、ありがとうございました。
Databricks, Delta Lake の魅力が少しでも伝われば幸いです。
参考
鎌田 義章 (執筆記事一覧)
2023年4月入社 アプリケーションサービス本部ディベロップメントサービス3課