【備忘】Delta Lake の過去データ保持とVacuum、ログの動きを Microsoft Fabric で確認する

## はじめに

VACUUM と、Delta Lake のDELETE RETENTION 期間について詳細の動きを理解したかったのでメモ

## 参考：

- https://qiita.com/naoyabe/items/f1fa063d52eed4d85d9a
- https://learn.microsoft.com/ja-jp/azure/databricks/delta/history
- https://www.epochconverter.com/

## 確認内容

https://delta.io/blog/remove-files-delta-lake-vacuum-command/#:~:text=Delta%20Lake%20doesn%27t%20physically%20remove%20files%20from%20storage,of%20vacuuming%20is%20to%20save%20on%20storage%20costs.

にしたがって確認していきます。

まずはテーブルの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3ac89fb6-4475-cd0f-7738-c244a94f92d2.png)

レイクハウスのファイルをレイクハウスの画面から見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/dcd408a3-2d99-c64b-d208-5b3aebaf9c3d.png)



ローカルで見たいので、[OneLake file explorer](https://learn.microsoft.com/ja-jp/fabric/onelake/onelake-file-explorer)で参照します。

対象のレイクハウスをローカルで常に保持するとスムーズです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d2bbe6d2-0062-a9db-36f1-9425c759cd17.png)

delta log 内のファイルをローカルPCから見ていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/36346c1e-31b4-fa01-1904-893d53b529f6.png)


vscodeで見てみると、操作が実行された時刻とその内容が確認できます。saveAsTable がCREATE AS SELECT で操作されていることがわかります。※編集されるとDelta Lake が正常に動作しなくなるので、別の場所コピーしてみています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/429e9b09-9230-b727-d4e2-9e5b17cc6e8b.png)


add に注目します。some_people フォルダ内のparquet ファイルが追加されたことがデータ処理に関する統計情報と共に記録されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d948dbc9-4fac-1852-ea58-e3279748fcb7.png)

<details>
<summary>こんなJSONです。参考まで。全体※クリックで展開します</summary>
<div>

```JSON:
{
    "commitInfo": {
        "timestamp": 1706855753887,
        "operation": "CREATE TABLE AS SELECT",
        "operationParameters": {
            "isManaged": "true",
            "description": null,
            "partitionBy": "[]",
            "properties": "{}"
        },
        "isolationLevel": "Serializable",
        "isBlindAppend": true,
        "operationMetrics": {
            "numFiles": "1",
            "numOutputRows": "2",
            "numOutputBytes": "1283"
        },
        "tags": {
            "VORDER": "true"
        },
        "engineInfo": "Apache-Spark/3.4.1.5.3-110807746 Delta-Lake/2.4.0.8",
        "txnId": "5ee4af5c-7336-4c85-9a3f-cd57451091ff"
    }
}
{
    "protocol": {
        "minReaderVersion": 1,
        "minWriterVersion": 2
    }
}
{
    "metaData": {
        "id": "0f819072-52f0-48a1-b1c8-e2bf9b004ea9",
        "format": {
            "provider": "parquet",
            "options": {}
        },
        "schemaString": "{\"type\":\"struct\",\"fields\":[{\"name\":\"first_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"age\",\"type\":\"long\",\"nullable\":true,\"metadata\":{}}]}",
        "partitionColumns": [],
        "configuration": {},
        "createdTime": 1706855752966
    }
}
{
    "add": {
        "path": "part-00000-6b9740b2-edec-401f-b975-e9c879e1d6a3-c000.snappy.parquet",
        "partitionValues": {},
        "size": 1283,
        "modificationTime": 1706855753779,
        "dataChange": true,
        "stats": "{\"numRecords\":2,\"minValues\":{\"first_name\":\"bob\",\"age\":3},\"maxValues\":{\"first_name\":\"sue\",\"age\":5},\"nullCount\":{\"first_name\":0,\"age\":0}}",
        "tags": {
            "VORDER": "true"
        }
    }
}

```

</div>

</details>


続きのコードを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/46970d38-6bd7-3eac-13c9-6f35dbd5ef03.png)


delta lake のフォルダは以下のようになりました。Parquet が増えています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/260167c8-0349-04ac-4acc-986a890c9e86.png)

ログも増えています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ad28bfe1-f16d-21b2-e759-d09915d26056.png)

追加されたログには内容は以下のように、parquet が増えたことを指すaddが記載されています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d9a8ebc9-c676-24ba-e587-a31166eab963.png)

続きのコードは上書き操作です。2件のテーブルとなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/5238ab3d-4905-099e-9e48-27f14e84f312.png)

parquet ファイルが増えています。過去のparquet ファイルはタイムトラベル用に使える状態で残されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/944db5ca-2cb9-e95c-2d65-3176fed9e276.png)

ログは以下のようになってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d1777719-c747-ec2c-9f4a-863ebabef663.png)

add と remove に注目します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b9f63931-760b-4539-fba5-1b3c1c358c5a.png)

overwrite 操作により全く新しいバージョンのparquetがaddされたタイミングで、以前のデータを含む2点のファイルがremoveされました。

ここでVacuumをしてみます。vacuumの既定値である、delta.deletedFileRetentionDuration は7日間になっているため、先ほどのファイルは対象となりません、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2d0e81ea-97b9-f4ed-7f6f-d86c4923895d.png)


0時間（removeされたらすぐ削除）をDRY RUN してみると先ほどの2点のファイルが対象となっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e57caca5-3393-9855-e78d-5386f4a46084.png)

## 削除時の経過時間はどのように決まる？

削除の対象時間はどのように決まるかを確かめます。

"part-00000-7b54faa1-8076-4593-bb27-2797feb8fd41-c000.snappy.parquet" の　deletionTimeStampは1706856302573でした。

これは日本時間で2024年2月2日 金曜日 15:45:02.573です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/8091fb89-fdeb-563a-ff71-564886ebcb0d.png)


このlog内の値を、1706251560000 に変えればremove 後7日が経過しているといえるはずです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/eea09c92-72b7-8986-564c-3a1fb8be8bcb.png)

実際にOneLake file explorer から変えてみましたが、削除対象にはなりませんでした。

三日後にRetain 72 hours で再実行してみたら対象になったので、履歴情報がベースのようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e0e9fcc4-6f74-518b-ae6d-546bbad80910.png)

履歴情報はどうやらトランザクションログのファイルタイムスタンプで決まっていました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/bfde8ad8-0fc0-b410-6c30-82aacf16cf01.png)

ファイルのタイムスタンプ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/46246b22-9938-3b7b-058f-6eafe6c8130e.png)

もう一度最新のlogファイルを更新してタイムスタンプを変えてみます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/13bcec51-31ac-b4f4-1579-96df7dc35d06.png)


そうすると、History の結果も変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a97aaeb0-828e-ae4f-2fef-0def9b849b4d.png)

ただし、先ほどはVACUUM対象になったものは以前VACUUM対象です。

parquet のタイムスタンプもいじってみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/57e76ab5-0299-a6ce-6642-e0e675ee2fa0.png)

すると、bk（トランザクションログに記録されていないファイル）が追加された代わりに、タイムスタンプをいじって時間のかわったファイルは対象にならなくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b9167b08-d77d-d9a3-510b-dc61ba836701.png)

1時間経過で削除の場合、対象としてタイムスタンプ更新ファイルは出てきません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a1e4d248-346f-5373-bf10-1bfc87785e9c.png)

0時間の場合、すべてのファイルが対象になりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/c278d28e-0152-5a28-945e-d33f3f18f661.png)

また、試しにトランザクションログのremove行を削除すると、削除対象はbkファイルのみ（トランザクションログに記載のないファイル）となりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/cc4c29f2-c2d9-569c-a97f-9a42db85f93b.png)


## 考察結果：
以下のようにVACUUM対象が特定されるようです。

1. removeされたファイルと、トランザクションログに記載のないファイルは候補となる
1. 1のうち、VACUUM に指定した時間とファイルの更新日時を比較して選定(通常はコミットのタイミングと同一）

OSSなのでコード見ればわかるのかもしれませんが、このように確認してみたという記事でした