「このデータ、Snowflakeにロードするほどではないが、たまにSQLで見たい」——そんな要件はデータ基盤の現場で必ず出てきます。S3にParquetやJSONを置いたまま、ロードせずにテーブルとしてクエリできるのがExternal Tables(外部テーブル)です。ただし内部テーブルと同じ感覚で使うと、パーティション設計やメタデータ更新のところで性能とコストの落とし穴が待っています。本稿では外部テーブルの仕組みとS3レイアウトの勘所、ロードとの使い分け、そして正常進化としてのIceberg Tablesまでを、AWS上でSnowflakeを設計・運用してきた立場から整理します。
01「ロードしない」という選択肢
External Tables(外部テーブル)は、S3などの外部ステージに置いたファイルを、あたかもSnowflake内部のテーブルであるかのようにクエリできる機能です。データはS3に置いたままで、Snowflakeへコピーは行いません。位置づけとして重要なのは、外部テーブルが読み取り専用である点です。INSERTやUPDATEなどのDMLはできず、できるのはSELECTと結合だけです。逆に言えば、S3上の生データを「そのまま参照する窓」を作る用途に特化しています。ETLで一度取り込むほどでもないアーカイブ、他システムがS3に吐き出したログ、データレイクの探索的な分析といった場面が典型です。対応フォーマットはCSV・JSON・Avro・ORC・Parquetで、XMLは対象外です。
02S3レイアウトと外部テーブルの定義
外部テーブルの各行は、まずVALUEというVARIANT型の1カラムとして展開されます。そこから必要な列を式で切り出して仮想列を定義するのが基本形です。たとえばCSVならc1 varchar as (value:c1::varchar)、Parquet/JSONならvalue:"order_id"::numberのように、キーや位置を指定して型付けします。S3への接続はストレージ統合(Storage Integration)オブジェクト経由で、Snowflake側のIAMロールにS3バケットへの読み取り権限を与える形になります。閉域要件があるなら、S3へのアクセスをAWS PrivateLink経由に寄せ、バケットはKMS(SSE-KMS)で暗号化しておくのが定石です。
03パーティションで不要ファイルを枝刈りする
外部テーブルの性能を決める最大の要因がパーティション設計です。Snowflakeにはマイクロパーティションのような内部統計がないため、「どのファイルを読まずに済ませるか」をこちらが設計してあげる必要があります。鍵になるのがMETADATA$FILENAMEという擬似列で、これは各行が属するS3上のファイルパスを返します。このパスをPARTITION BY句の中で式として切り出し、パーティション列を定義します。たとえばlogs/2018/08/05/log.parquetのような日付プレフィックスなら、date_part date as to_date(split_part(metadata$filename,'/',2)||'/'||split_part(metadata$filename,'/',3)||'/'||split_part(metadata$filename,'/',4),'YYYY/MM/DD')のように書きます。こうしておくと、WHERE句で日付を絞ったときにSnowflakeが該当プレフィックスのファイルだけを走査し、それ以外を枝刈りできます(図1)。
dt=YYYY-MM-DD/形式のプレフィックスで区切り、PARTITION BYを最初から定義。クエリで触れるプレフィックスだけを読む構成にし、想定外の走査を未然に防いでいます。S3側の「プレフィックス=疑似ディレクトリ」の考え方を、そのまま枝刈りキーに写像するのがコツです。なお、Hiveメタストアなど外部の管理系と同期させたい場合はPARTITION_TYPE = USER_SPECIFIEDを指定し、ALTER EXTERNAL TABLE … ADD PARTITIONでパーティションを手動追加する方式も選べます。
04メタデータの鮮度:AUTO_REFRESHとS3イベント通知
外部テーブルは、S3にどんなファイルが存在するかというメタデータを内部に持っています。新しいファイルがS3に届いても、このメタデータが更新されなければクエリ結果には現れません。更新方法は二つで、ALTER EXTERNAL TABLE … REFRESHによる手動更新と、AUTO_REFRESH = TRUEによる自動更新です。自動更新はS3のイベント通知(Amazon S3 Event Notifications)を使い、新規オブジェクトの作成イベントをSQSキュー経由でSnowflakeが受け取り、差分だけをメタデータへ反映する仕組みです。IAMでSnowflake側にSQS購読権限を渡す形になります。
一点、仕様上の注意として、前述のPARTITION_TYPE = USER_SPECIFIEDを使う外部テーブルではAUTO_REFRESHはサポートされません。手動管理を選ぶなら、パーティション追加とREFRESHの運用フローをセットで設計しておく必要があります。
05ロードとの使い分け:性能特性とマテビュー
ここが最も判断を誤りやすいポイントです。外部テーブルは便利ですが、内部テーブルと同じ速度は出ません。マイクロパーティション統計やクラスタリングの恩恵がなく、実体はS3上のファイルを読みに行くため、繰り返し叩かれるダッシュボードのバックエンドには向きません。目安として、探索・一時分析・アーカイブ参照は外部テーブル、反復する本番クエリはロードが基本線です。どうしても外部テーブル上のホットなクエリを速くしたい場合は、Enterprise Edition以上で外部テーブルにマテリアライズドビューを張る手があります。マテビューが結果を保持することで、下地の外部テーブルへ都度クエリするより高速になります。
06Iceberg Tablesという正常進化
「S3にデータを置いたまま扱いたい」という動機は、いま多くのケースでApache Iceberg Tablesに向かっています。外部テーブルが読み取り専用でSnowflake独自の枠組みだったのに対し、Icebergはオープンなテーブルフォーマットで、ACIDトランザクション・スキーマ進化・スナップショットを備え、Parquetのデータファイルとマニフェストで構成されます。S3への接続には、外部テーブルのストレージ統合に相当する外部ボリューム(External Volume)を作成し、そこにIAMの接続情報を持たせます。運用形態は大きく二つで、Snowflakeがカタログを持つSnowflake管理では読み書き・コンパクションなどのメンテナンスまでフル機能が使え、AWS Glueなどの外部カタログと統合する形では、他エンジンとの相互運用性を取りつつSnowflakeはおもにReadを担います。
07まとめ:現場の判断基準
外部テーブルは「ロードしないで読む」ための強力な道具ですが、内部テーブルの代替ではありません。判断の軸は三つに整理できます。第一に、S3レイアウトを日付などのプレフィックスで設計し、METADATA$FILENAMEからパーティション列を切り出して枝刈りを効かせること。第二に、メタデータの鮮度はAUTO_REFRESH+S3イベント通知で差分反映に寄せ、手動REFRESHの全走査リスクを避けること。第三に、探索・アーカイブは外部テーブル、反復する本番クエリはロード、S3に置いたまま高速に扱いたいならIcebergへ、という使い分けです。いずれもSnowflakeがAWS上で動く前提を活かし、IAM・PrivateLink・KMS・SQSといったAWS側の設計とセットで組むことで、性能とコストと鮮度のバランスが初めて取れます。
参考情報(一次情報)
- Introduction to external tables | Snowflake Documentation
- CREATE EXTERNAL TABLE | Snowflake Documentation
- Apache Iceberg tables | Snowflake Documentation
- Configure an external volume for Amazon S3 | Snowflake Documentation
- Amazon S3 Event Notifications - Amazon S3 User Guide
- Organizing objects using prefixes - Amazon S3 User Guide
EMWはAWS×Snowflakeで、S3レイアウト設計から外部テーブル・Iceberg基盤の構築・運用までワンストップでご支援します。まずはお気軽にご相談ください。
相談する