Athenaで作成したS3上のIcebergテーブルをSnowflakeから参照してみる

# これはなに
Apache Iceberg というオープンソースのデータテーブル形式について、最近データエンジニアリング界隈で耳にすることが増えてきました。
これはいわゆる「レイクハウスアーキテクチャ」におけるテーブルフォーマットの一つとされ、従来のデータレイクにおいて課題となる以下の点に対する解決策を提示しているといえます。

* トランザクション運用、安全な更新
* パーティションやスキーマ、パフォーマンスチューニングにおける柔軟性
* 変更履歴管理、バージョンロールバック

加えて、Icebergおよびレイクハウスアーキテクチャの提供する重要な価値としては「相互運用性」が挙げられます。
今回はIceberg形式のオープンさを体感するために、Glueデータカタログで定義されたテーブルをSnowflakeで参照するユースケースを再現してみます。

構成イメージはこちらです。

![スクリーンショット 2024-06-25 17.41.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/2e3d1138-a743-238f-6498-2561b537fbb9.png)

# 検証
## 1. AthenaでIcebergテーブルを作る
Icebergテーブルを作る方法は、Sparkジョブを使う、Glueクローラーを動かす等いくつか方法論がありますが、今回はSQLクエリから作成してみます。

```sql
CREATE TABLE lake_customers (
  id int, 
  created_at timestamp, 
  name string,
  member_rank string
)
LOCATION 's3://{bucket_name}/{path}/'
TBLPROPERTIES ('table_type' ='ICEBERG');
```

すでにAthenaから参照できるデータがあれば、CTAS(CREATE TABLE AS SELECT)でデータ投入することも可能です。
今回は検証のため、手動でサンプルデータを投入してみます。

```sql
INSERT INTO lake_customers VALUES
(1, timestamp'2024-06-02 10:00:00', 'Dummy Name1', 'bronze'),
(2, timestamp'2024-06-03 11:00:00', 'Dummy Name2', 'bronze'),
(3, timestamp'2024-06-04 12:00:00', 'Dummy Name3', 'silver'),
(4, timestamp'2024-06-05 13:00:00', 'Dummy Name4', 'gold');
```

ここでS3を見てみると、 `data` `metadata` という2つのパスが切られ、それぞれファイルが生成されていることが確認できます。

![スクリーンショット 2024-06-25 17.52.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/5e04142d-9556-c633-f842-8a26b906c997.png)

`data` の方には parquet フォーマットでデータの実体が保存されています。
`metadata` の方には、metadata.json と avro の2種類のファイルが保存されています。

上記は更新やデータ追加のたびに新たなパスが切られ、バージョンごとにファイルが増えていくような挙動となっているようです。

また、ここでAWS Glueのコンソールを開くと、データカタログが自動で作成されていることがわかります。
![スクリーンショット 2024-06-25 17.59.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/992e40d7-0910-cc48-da34-395dacbb4d3f.png)

Glue側のジョブ起動操作なしに、カタログ登録が為されるのは楽ですね。

## 2. Snowflakeから参照する

SnowflakeからGlueデータカタログを参照するためには、事前に「統合ボリューム」「カタログ統合」の設定が必要です。設定には、AWS側のIAMポリシー、IAMロールの作成/編集権限が必要です。

https://docs.snowflake.com/ja/user-guide/tables-iceberg-create#create-an-iceberg-table-with-aws-glue-as-the-catalog

権限設定の詳細は公式ドキュメントを参照いただくとして、ざっくりの手順としては以下のような操作を行います。

```sql
CREATE EXTERNAL VOLUME exvol
   STORAGE_LOCATIONS =
      (
         (
            NAME = 'my-s3-ap-northeast-1'
            STORAGE_PROVIDER = 'S3'
            STORAGE_BASE_URL = 's3://{bucket}/{path}/'
            STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::xxx:role/snowflake_iceberg_role'
            ENCRYPTION=(TYPE='xxx')
         )
      );

CREATE CATALOG INTEGRATION glueCatalogIntegration
   CATALOG_SOURCE=GLUE
   CATALOG_NAMESPACE='{DATABASE_NAME}'
   TABLE_FORMAT=ICEBERG
   GLUE_AWS_ROLE_ARN='arn:aws:iam::xxx:role/snowflake_iceberg_role'
   GLUE_CATALOG_ID='{AWS_ACCOUNT_ID}'
   GLUE_REGION='ap-northeast-1'
   ENABLED=TRUE;
```

上記が完了すると、外部データカタログが参照できるようになります。Glue側のカタログ情報を使って、Snowflake側のテーブルを作成します。

```sql
CREATE ICEBERG TABLE lake_customers
  EXTERNAL_VOLUME='exvol'
  CATALOG='glueCatalogIntegration'
  CATALOG_TABLE_NAME='lake_customers';
```

作成したテーブルにクエリを投げてみます。

![スクリーンショット 2024-06-25 15.51.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/5ce92ce7-cc5e-9b64-c32e-041233b23616.png)

Athena上で投入したデータがSELECTできることを確認できました。

## 3.データ追加を試す
次に、Athena上でデータ追加を試してみます。

```sql
INSERT INTO customers VALUES
(5, timestamp'2024-06-06 10:00:00', 'Dummy Name5', 'bronze'),
```

データの変更をSnowflake側に反映するには、メタデータのリフレッシュが必要です。
Snowflake上で以下のクエリを流します。

```sql
ALTER ICEBERG TABLE lake_customers REFRESH;
```

Snowflake上でSELECT文を投げると、追加されたレコードが反映されていることを確認できます。

![スクリーンショット 2024-06-25 15.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/ba79c67b-28bc-3a5c-d182-d466fc366568.png)

## 4.データ更新を試す
次に、Athena上でデータ更新をしてみましょう。

```sql
UPDATE lake_customers SET member_rank = 'silver'
WHERE id = 2;
```

その後Snowflake上でのリフレッシュを試みると、以下のエラーが発生してしまいました。

```
SQL Compilation error:
Iceberg tables using row-level deletes are not supported.
```

ここで、Snowflakeの[ドキュメント](https://docs.snowflake.com/ja/user-guide/tables-iceberg-create#create-an-iceberg-table-with-aws-glue-as-the-catalog)を再度確認してみます。

![スクリーンショット 2024-06-25 18.37.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/669ba332-eb94-8718-b5c7-15248a347314.png)

Glueカタログのテーブル利用には制限があることがわかりました。

# まとめ
Glueデータカタログで定義されたIcebergテーブルは、Snowflakeで参照することができますが、一部制限があることがわかりました。
具体的には「データ追記は発生するが、更新/削除が発生しないテーブル」において利用が可能、といえます。（2024/06時点）

上記のような課題を解消するためのアプローチとして、Unity CatalogやPolaris Catalogといったカタログ仕様が登場してきています。こうした相互運用性を高める流れによって、今後データエンジニアリング周りのアーキテクチャ選定はより自由になっていくことが期待されます。

## appendix

S3/Athenaに対して各種データソースからデータを集約する部分の処理については、SaaSのTROCCO®を活用することでプログラミングなしで簡単に実現ができます。S3へのファイル配置、parquet変換のみならず、Glueデータカタログへのテーブル登録まで自動で実行される機能が提供されています。

https://documents.trocco.io/docs/data-destination-s3-parquet

フリープランがありますので、無料で試すことも可能です。

https://trocco.io/lp/index.html

こうしたデータエンジニアリングのトレンドを押さえつつ、最適なデータ基盤の構築およびデータ活用を支援するサービスを、弊チームにて提供しています。ご興味があればぜひお問い合わせください。

https://dataorchestration.cloud/solution