【S3 Tables】スナップショット削除の実行タイミングを確認してみた

【S3 Tables】スナップショット削除の実行タイミングを確認してみた

Clock Icon2025.03.18

データ事業本部の川中子(かわなご)です。

S3 TablesはIceberg形式のテーブルで作成されるメタデータファイルが自動で管理されています。
しかし自動で管理されているからこそ、スナップショットの削除タイミングなどが見えにくいとも言えます。

今回はS3 Tablesの自動メンテンス機能が実行されるタイミングについて調べてみました。
個人情報の取り扱いなどで、データの保持期間をコントロールしたい場合の参考になれば幸いです。

結論

最初に本検証で分かった内容をまとめておきます。

  • スナップショットと非参照ファイルの削除は日次で実行される
  • 1時間以上経過したスナップショットを削除対象としても、あくまでも日次で削除される
  • 削除日次はAWS側の固定スケジュールではなく、テーブル作成時刻に依存する

検証準備

Lambdaを作成する

まずは検証に使用するLambdaを作成します。
大まかな処理は以下の2点で、メンテンスジョブの履歴確認結果を定期的に格納します。
30分の処理実行毎に新しいスナップショットも併せて作成されています。

  • get-table-maintenance-configurationを30分毎に実行
  • 結果をmaintenance_job_status_checkテーブルに格納

具体的なソースコードは以下に置いておきます。

lambda_function.py
import boto3
import datetime
import pyarrow as pa
from pyiceberg.catalog import load_catalog

def lambda_handler(event, context):

    # カタログ読み込み用の変数
    region = "us-west-2"
    account_id = {アカウントID}
    s3table_bucket_name = "cm-kawanago-test"

    # テーブル指定に関連する変数
    database_name = "20250218_namespace"
    table_name = "maintenance_job_status_check"

    # カタログを読み込み
    catalog =  load_catalog(
            "S3TablesCatalog",
            **{
                "type": "rest",
                "warehouse": f"{account_id}:s3tablescatalog/{s3table_bucket_name}",
                "uri": f"https://glue.{region}.amazonaws.com/iceberg",
                "rest.sigv4-enabled": "true",
                "rest.signing-name": "glue",
                "rest.signing-region": region,
            },
        )

    # 日本時間に調整するためのタイムデルタ
    td = datetime.timedelta(hours=9)
    # 実行日時を取得
    now_jst = datetime.datetime.now() + td
    now_jst_str = datetime.datetime.strftime(now_jst, "%Y-%m-%d %H:%M:%S")

    # メンテンスジョブの履歴を取得
    s3tbl_client = boto3.client('s3tables')
    response = s3tbl_client.get_table_maintenance_job_status(
        tableBucketARN = f"arn:aws:s3tables:{region}:{account_id}:bucket/{s3table_bucket_name}",
        namespace = database_name,
        name = table_name
    )

    # テーブル作成用の辞書
    table_dict = {}

    for k, v in response["status"].items():

        try:

            # 最終実行時日時を日本時間に変換
            ts_jst = v["lastRunTimestamp"] + td
            ts_jst_str = datetime.datetime.strftime(ts_jst, "%Y-%m-%d %H:%M:%S")

        except:

            # 取得できなかった場合
            ts_jst_str = "Not_Yet_Run"

        # カラムと日時の値を格納
        table_dict[k.lower()] = ts_jst_str

    # 実行日時をデータへ格納
    table_dict["execute_timestamp"] = now_jst_str

    # 取得した結果をテーブルへ格納
    add_table = pa.Table.from_pylist([table_dict])
    tbl = catalog.load_table(f"{database_name}.{table_name}")
    tbl.append(add_table)

    return {
        "status_code": 200,
        "results": table_dict
    }

pyicebergのインストールについては以下の記事を参考にしてます。

https://dev.classmethod.jp/articles/tried-to-write-to-iceberg-tables-in-s3-tables-from-lambda-using-pyiceberg/

私はローカルでインストールしたものにlambda_function.pyを併せてzipで固めて、
S3にファイルを置いてからLambdaのソースコードとしてアップロードしました。
-t {dir}の部分は新しく作成した空のフォルダを指定すると扱いやすいと思います。

pip install -t ./{dir} --only-binary=:all: --platform manylinux2014_x86_64 "pyiceberg[glue,pyarrow]"

メンテンスジョブの設定を変更する

頻繁にメンテンスジョブが実行されるように、メンテンスジョブの設定を変更しておきます。
1時間以上経過しているスナップショットが削除され、かつ最低保持数が1つになります。

aws s3tables put-table-maintenance-configuration \
    --table-bucket-arn {テーブルバケットのARN} \
    --namespace 20250218_namespace \
    --name maintenance_job_status_check \
    --type icebergSnapshotManagement \
    --value '{"status":"enabled","settings":{"icebergSnapshotManagement":{"minSnapshotsToKeep":1,"maxSnapshotAgeHours":1}}}'

上のコマンドは特に何もアウトプットがないので、設定が反映されているか確認します。
しっかり設定が反映されているので問題なさそうです。

aws s3tables get-table-maintenance-configuration \
    --table-bucket-arn {テーブルバケットのARN} \
    --namespace 20250218_namespace \
    --name maintenance_job_status_check
{
    "tableARN": {テーブルのARN},
    "configuration": {
        "icebergCompaction": {
            "status": "enabled",
            "settings": {
                "icebergCompaction": {
                    "targetFileSizeMB": 512
                }
            }
        },
        "icebergSnapshotManagement": {
            "status": "enabled",
            "settings": {
                "icebergSnapshotManagement": {
                    "minSnapshotsToKeep": 1,
                    "maxSnapshotAgeHours": 1
                }
            }
        }
    }
}

結果を見てみる

数日後に結果のテーブルを見ると、想定通りデータが登録されていました。
0,1行目はまだメンテンスが実施されておらず、Not_Yet_Runになっています。

スクリーンショット 2025-03-17 14.15.42

テーブルだと全体が把握しづらいので、グラフで描画してみました。
x軸にテーブルへのデータ連携時刻、y軸は各メンテンスジョブの実施時刻を描画してます。

スクリーンショット 2025-03-17 14.20.19

icebergunreferencedfileremovalicebergsnapshotmanagementはほぼ同じ時刻で、
icebergcompactionはより頻繁に実施されているようです。

コンパクションの具体的な実施時刻を見てみると、12:51以降で3時間毎に実施されていました。

data["icebergcompaction"].unique()[1:10]

array(['2025-03-10 12:51:21', '2025-03-10 15:51:59',
       '2025-03-10 18:51:23', '2025-03-10 21:51:59',
       '2025-03-11 00:51:56', '2025-03-11 03:51:30',
       '2025-03-11 06:51:25', '2025-03-11 09:52:01',
       '2025-03-11 12:51:21'], dtype=object)

スナップショットの削除は日次で12:51頃に実施されています。

data["icebergsnapshotmanagement"].unique()[1:10]

array(['2025-03-10 12:51:49', '2025-03-11 12:57:25',
       '2025-03-12 12:56:57', '2025-03-13 12:57:05',
       '2025-03-14 12:52:02', '2025-03-15 12:57:17',
       '2025-03-16 12:51:59'], dtype=object)

以前別の検証でスナップショット削除を確認した際は全く違う時刻に実施されていたので、
この12:51という時刻は 特にAWS側のスケジュールというわけではなく
テーブル作成や最初のデータ投入の時刻に合わせてスケジュールされているようです。

さいごに

メンテンスの設定は1時間以上経過しているスナップショットを削除対象としていましたが、
実際の スナップショット削除は日次で実行されている ことが分かりました。
ジョブ自体は日次で実行され、その際に条件を満たすスナップショットが削除されるようです。

また参照されていないファイルの削除も同タイミングで実行されていましたが、
こちらもジョブ自体は日次で実行されており、条件を満たす場合は削除される仕様だと思われます。
なお本検証では、テーブルバケットのメンテンス設定はデフォルトのままにしていました。

コンパクションは3時間ごとに実行されていましたが、これがどの場合も適用されるのかは不明 です。
圧縮単位の設定はデフォルトの512MBのままでしたが、たまたま今回の検証によるデータ蓄積量が、
3時間ごとにコンパクションの対象になっていた可能性も否定できないためです。

以上、S3 Tablesのメンテンスジョブの実行タイミングの検証でした。
少しでも参考になれば幸いです、最後まで閲覧頂きありがとうございました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.