🧊

Snowflake を使って Data Lake を Iceberg 化してみる

2024/12/16に公開

📜 この記事は

Snowflake Advent Calendar 2024 Series 2 - Day 16 の記事になります。Snowflake で Sales Engineer をしております、@tmasuo がお届けします。
年々 Snowflake Advent Calendar の枠が埋まっていくのが早くなっていること、そしてテーマも多岐にわたって行っていることにとても驚いています。そんな中、Iceberg ネタでお送りできればと思っております。

🧊 Iceberg Tables リリースラッシュだった 2024 年

2024 年は Iceberg Tables 関連のリリースラッシュでした。Release Note の Recent Snowsight and feature releases に記載された 2024 年 11 月までのリリースから Iceberg と検索して抽出してみたところ、以下のようなリリースがありました。

ざっくりまとめてしまうと、

  1. Snowflake Summit (2024 年 6 月) で GA リリースがアナウンスされた
  2. その後色々な既存機能 (データエンジニアリング、Native App、DCR) との連携が進んだ
  3. Snowflake BUILD (2024 年 11 月) でまたさらにいろいろとリリースされた

といった具合です。

今年 GA された機能をは思えないくらいのリリース速度です。Iceberg エコシステムが大きなうねりとなっていることが伺えますね。

なぜ Iceberg エコシステム、ひいては Open Table Format (OTF) が大きなうねりとなってきたか、その誕生の背景であったり Iceberg の特徴については以下のブログなどがとても参考になります。
https://bering.hatenadiary.com/entry/2023/07/17/235246
https://zenn.dev/dataheroes/articles/iceberg-the-definitive-guide-summary

また SnowVillege Slack でも非常に勉強になる議論が繰り広げられているのでよろしければ以下のリンクから参加して覗いていただければと思います。
https://usergroups.snowflake.com/snowvillage/
すでに参加済みの方は #iceberg #iceberg-the-definitive-guide あたりにどうぞ!

そのうえで、Iceberg で享受できるメリットを素早く取り込むことができる機能がリリースされているので、そちらを試してみることにこの記事ではフォーカスしてみたいと思います。

🏞️ "なんかありそうな" Data Lake

Iceberg 化してみる "なんかありそうな" Data Lake ですが、TPCH-SF1000 のデータを S3 にアンロードしてみたいと思います。
このとき、

  • カラムに日付が含まれるテーブル orders lineitem は Hive-style パーティションを実施して Parquet でアンロード
  • カラムに日付が含まれないテーブルは CSV でアンロード

してみたいと思います。

use schema iceberg_db.ice;

-- ファイルフォーマットの作成
-- csv
create or replace file format my_csv_format
type = csv
parse_header=true;
-- parquet
create or replace file format my_parquet_format
type = parquet
use_vectorized_scanner = true;

-- データのアンロード(一部抜粋)
-- customer
copy into @common_dl/customer/ from snowflake_sample_data.tpch_sf1000.customer
file_format = my_csv_format
header = true;

-- orders
copy into @common_dl/orders/ from snowflake_sample_data.tpch_sf1000.orders
partition by ('year=' || to_varchar(o_orderdate, 'YYYY') || '/month=' || to_varchar(o_orderdate, 'MM') || '/day=' || to_varchar(o_orderdate, 'DD'))
file_format = my_parquet_format
header = true;

ここまでで "なんかありそうな" Data Lake が構成されました。

customer (CSV)

orders (Parquet, Hive-style partitioned)

🚀 Snowflake で Iceberg 化してみる

こちらで構成された Data Lake を Snowflake で Iceberg 化してみたいと思います。まずは Iceberg Tables を作成します。

-- External Volume の作成
create or replace external volume iceberg_external_volume
  STORAGE_LOCATIONS =
    (
      (
        NAME = 'your-volume-name'
        STORAGE_PROVIDER = 'S3'
        STORAGE_BASE_URL = 's3://your-bucket/path/'
        STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789123:role/your-iam-role'
        STORAGE_AWS_EXTERNAL_ID = 'your-external-id'
      )
    );


-- Iceberg Tables の作成(一部抜粋)
-- customer
create or replace iceberg table customer
(
"C_ADDRESS" TEXT NOT NULL,
"C_CUSTKEY" NUMBER(38, 0) NOT NULL,
"C_NAME" TEXT NOT NULL,
"C_NATIONKEY" NUMBER(38, 0) NOT NULL,
"C_PHONE" TEXT NOT NULL,
"C_ACCTBAL" NUMBER(12, 2) NOT NULL,
"C_MKTSEGMENT" TEXT,
"C_COMMENT" TEXT
)
catalog = 'snowflake'
external_volume = 'iceberg_external_volume'
base_location = '';

-- orders
create or replace iceberg table orders
(
"O_ORDERPRIORITY" TEXT NOT NULL,
"O_ORDERSTATUS" TEXT NOT NULL,
"O_TOTALPRICE" NUMBER(12, 2) NOT NULL,
"O_CLERK" TEXT NOT NULL,
"O_ORDERKEY" NUMBER(38, 0) NOT NULL,
"O_CUSTKEY" NUMBER(38, 0) NOT NULL,
"O_ORDERDATE" DATE NOT NULL,
"O_SHIPPRIORITY" NUMBER(38, 0) NOT NULL,
"O_COMMENT" TEXT NOT NULL
)
catalog = 'snowflake'
external_volume = 'iceberg_external_volume'
base_location = '';

この時点では Iceberg Tables は空です。既存の Data Lake からデータを取り込んでみたいと思います。このときに非常に便利な機能が COPY コマンドの LOAD_MODE オプションです。
https://docs.snowflake.com/en/user-guide/tables-iceberg-load
Iceberg のデータフォーマットは既存の Parquet を活かすこともできるため、このオプションを利用することで、

  • CSV, JSON, Avro, ORC などの Parquet でないファイルは変換
  • Parquet は物理的にファイルをコピー

することができるため、データボリュームが大きくなりがちな Data Lake の既存資産をうまく活かしながら Iceberg への変換を行うことができます。

-- Iceberg テーブルへの取り込み(一部抜粋)
-- customer
copy into customer from @common_dl/customer/
file_format=my_csv_format
load_mode = full_ingest
purge = true
match_by_column_name = case_sensitive;

-- orders
copy into orders from @common_dl/orders/
file_format=my_parquet_format
load_mode = add_files_copy
purge = true
match_by_column_name = case_sensitive;

実際の S3 の物理的なファイル構成はこの記事では割愛しますが、こちらのブログ記事が参考になるかと思います。

http://dev.classmethod.jp/articles/iceberg-tables-load-with-add-files-copy/

これで既存の "なんかありそうな" Data Lake を Iceberg 化できてしまいました!

💡 補足: DDL 作成の便利コマンド

Snowflake で Iceberg Tables を定義する DDL でカラム名を指定していますが、こちらは generate_colum_descriptioninfer_schema から定義を生成できます。

-- CSV
select generate_column_description(array_agg(object_construct(* exclude filenames)), 'table')
from table(
  infer_schema(
    location=>'@common_dl/customer/',
    file_format=>'my_csv_format'
  ));

-- Parquet
select generate_column_description(array_agg(object_construct(* exclude filenames)), 'table')
from table(
  infer_schema(
    location=>'@common_dl/orders/',
    file_format=>'my_parquet_format'
  ));

❄️ Snowflake で Iceberg を使うメリット

主に以下の 3 点があると思っています。

  • 簡単にオンボードできる
  • Snowflake の機能をいろいろ利用できる
  • シンプルに相互運用を実現できる

⚡️ 簡単にオンボードできる

本記事で取り上げた通り、DDL と COPY コマンドだけで Iceberg が実現できるのは非常にシンプルな体験で良いと思いました。
LOAD_MODE が追加されたことで、既存の Parquet を再構築することなく Iceberg 化できることで、コスト効率良く Iceberg で Lakehouse を実現できました。
また、今回紹介した昨日は Snowpipe とも連携ができるので、既存の Data Lake にデータが流れ着く仕組みがあれば、Snowpipe によりイベント駆動で Iceberg 化することができてしまう点も、シンプルで良いです。

👉️ Snowflake の機能をいろいろ利用できる

Snowflake は柔軟な仮想ウェアハウスの指定によりワークロードを分離できます。もちろん仮想ウェアハウスの基本的なメリットである即座のスケールアップ・スケールアウトも実現できることから、Iceberg による Lakehouse を Snowflake が持つシンプルさ、スケーラブルさを活かしながら実現できます。
また、操作履歴や行方向・列方向のガバナンス機能も利用できますし、データ共有による社内外のエンティティを超えた共有も可能なため、ガバナンスと利活用を両立できる点もメリットになってきます。
また開発者目線では SQL は当然ながら、Snowpark による Python でのデータ操作や Dynamic Iceberg Tables、Snowflake Notebooks (GA しました!) や Streamlit in Snowflake でも取り回せる点も、Iceberg での Lakehouse を実現しつつもデータ・AI 利活用を止めないメリットを提供できると思います。
上記で紹介したいくつかの機能については以下の Quickstart で触れているのでぜひ参考にしてみてください。
https://quickstarts.snowflake.com/guide/getting_started_iceberg_tables/index.html?index=..%2F..index#0

↔️ シンプルに相互運用を実現できる

最後に、そもそも Iceberg/Lakehouse を適用していくモチベーションの 1 つとして "相互運用性"、というキーワードは外せません。Iceberg により様々なエンジンと連携できるようになる点、そして Snowflake がホストした Apache Polaris である、Snowflake Open Catalog に Snowflake のカタログを連携することで Spark からデータを読み取るなども実現できます。
Snowflake Open Catalog で実現できるユースケースなどは以下のチュートリアルでカバーされているのでぜひ参考にしてみてください。
https://other-docs.snowflake.com/en/opencatalog/tutorials/open-catalog-gs

✅ さいごに

2024 年は Iceberg が今後データ基盤の相互運用性を実現する上で重要な要素となってくることが示めされた大きな一年だったと思います。この Iceberg によるメリットを運用負荷低く、シンプルに実現するうえで、Snowflake で既存の Data Lake を Iceberg による Lakehouse にするのは 1 つの優れた選択肢になるかと思います。ぜひお試しください!!

Discussion