目次
はじめに
お久しぶりです。omkです。
2025年から忙しくてしばらくまともに技術キャッチアップが出来ていなかったんですが、
かなりIceberg周りでアップデートがあった年でしたね。
最後にIcebergのブログ書いたのがもう2年前らしく、気付いたらタイムトラベルでもしたかのように右も左も分からないようになってました。
AthenaでApache Icebergのテーブルをタイムトラベルしてみた
せっかく時間が出来たので更新情報をキャッチアップしつつ試しに使っていきます。
同じく遅れている人(失礼)も一緒にキャッチアップして追いついていきましょう!!
S3 Tables
S3 TablesではIceberg形式に対応したデータ分析特化のS3バケットです。(厳密にはS3 Tablesのデータの保存先バケットがテーブルバケット??)
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-tables.html
もともと汎用バケットでもIceberg形式のデータを保存してGlue DataCatalogでIcebergテーブルとして認識させることは出来ましたが、テーブルバケットではストレージ自体がネイティブにIcebergに最適化されているためパフォーマンスに優れているとか。
今回は以前作成した汎用バケットのIcebergテーブルをテーブルバケットに移行してみます。
やってみた
細かい作り方はドキュメントに記載があるのでざっくり書きます。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-tables-getting-started.html
テーブルバケットの作成と分析サービスへの統合
S3コンソールのナビゲーションペインでテーブルバケットを選択して画面に沿ってテーブルバケットを作成します。
出来ました。
これでデータの置き場所が出来ました。
分析サービスとの統合はLake Formationで設定されるんですね。
有効にします。
テーブルバケットをLake Formationで統合したことによってGlue Data Catalogにカタログが作成されました。

テーブルの作成とデータの挿入
ではテーブルを作っていきましょう。
移行をノートブックからSparkでやりたかったのでSageMaker Unified Studioを用いて操作します。
そういえばSageMaker Unified Studioも2025年頃に出たサービスですが、かなりスムーズにセットアップから利用まで出来て便利ですね。
昔のSageMaker Studioだと画面を開くだけでもかなり時間がかかった覚えがあるので手軽さが嬉しいです。
既にノートブック環境がほしいときの選択肢としてはこれがスタンダードになってるんじゃないでしょうか。
閑話休題、既存テーブルの確認。
df = spark.table("ricecooker.survey2")
df.printSchema()
df.show()
テーブルバケットに名前空間を作成。
名前空間はGlue Data Catalogのデータベースと同等のものらしいです。
import boto3
# Initialize S3 Tables client
s3tables_client = boto3.client('s3tables', region_name=region)
# Create the namespace
table_bucket_arn = "{ARN}"
namespace_name = "{namespace}"
response = s3tables_client.create_namespace(
tableBucketARN=table_bucket_arn,
namespace=[namespace_name]
)
作成した名前空間上にテーブルの作成。
import boto3
s3tables_client = boto3.client('s3tables', region_name='ap-northeast-1')
table_name = "survey2"
s3tables_client.create_table(
tableBucketARN=table_bucket_arn,
namespace=namespace_name,
name=table_name,
format='ICEBERG',
metadata={
'iceberg': {
'schema': {
'fields': [
{
'name': 'id',
'type': 'long',
'required': False
},
{
'name': 'grade',
'type': 'int',
'required': False
},
{
'name': 'comment',
'type': 'string',
'required': False
},
]
}
}
},
encryptionConfiguration={
'sseAlgorithm': 'AES256'
}
)
テーブルが作成できました。
ビジュアル的に分かりやすいですね。
(カラム名がイケてなくてちょちょっと直したため画像は移行元のカラムと差異があります)
テーブルが出来たのでデータを入れていきたいんですが、
ここからがLake Formationの領域になるのでややこしいです。
Lake Formationで権限が割り当てられていないとテーブルを参照しようとしても「TABLE_NOT_FOUND」のような応答になります。
今回はLake Formationの「Data lake administrators」に自分のIAMユーザーを登録して、SageMaker Unified Studioのロールに対象名前空間の操作権限を割り当てました。
では既存テーブルから取得したデータフレームをSparkで書き込み。
(省きましたがカラム名を変換してから書き込みしてます)
import pyspark.sql.functions as f
spark.conf.set("spark.sql.catalog.s3tablescatalog", "org.apache.iceberg.spark.SparkCatalog")
spark.conf.set("spark.sql.catalog.s3tablescatalog.catalog-impl", "software.amazon.s3tables.iceberg.S3TablesCatalog")
spark.conf.set("spark.sql.catalog.s3tablescatalog.warehouse", "arn:aws:s3tables:ap-northeast-1:accountid:bucket/omk-blog-lake-table-bucket")
df.writeTo("s3tablescatalog.ricecooker2.survey2").append()
ここまでできればデータの移行は完了です。
データの確認
それでは挿入したデータをSparkで取得してみます。
spark.sql("SELECT * FROM s3tablescatalog.ricecooker2.survey2").show()
取得出来ました。
コンソールからAthenaを開くとカタログからテーブルバケットを選択できるようになっています。
出なければ一度ログアウトしてみてください。
提供されるプレビュー用のクエリを実行。
クエリするユーザーにLakeFormationでの対象テーブルに対しての権限割り当てが必要なので注意。
--Use the following statement to query your S3 Table
SELECT * FROM "survey2" limit 10;
Athenaからもデータが取れるようになりました。
おわりに
好きなようにデータの読み書きが出来るようになりました。
LakeFormationでの権限操作が必要なので若干ややこしい面がありましたがそのあたりは慣れれば使えそうですね。
パフォーマンスについてはたった25件のデータでは当然差異が出なかったので体感出来る日が楽しみです。
以上、最後までお付き合いいただきありがとうございました。

アーキテクト課のomkです。
IoTが主食です。







