「このデータ、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)で暗号化しておくのが定石です。

現場のコツ:S3側のファイルサイズは効いてきます。Snowflakeの推奨は概ねParquetで256〜512MB程度、その他フォーマットで16〜256MB程度。数KBのJSONが数十万個、という「小ファイルの山」はメタデータ管理もクエリも重くなるため、可能ならバッチ側で適切なサイズに束ねてからS3へ置きます。

BI・SQL クライアント Snowflake(AWS) 仮想ウェアハウス (コンピュート) 外部テーブル定義 ・VALUE(VARIANT) ・パーティション列 ・メタデータで対象特定 ・不要ファイルを枝刈り 対象のみ取得 Amazon S3 バケット dt=2026-07-05/ part-*.parquet dt=2026-07-06/ part-*.parquet dt=2026-06-30/ 枝刈り dt=2026-06-29/ 枝刈り 走査対象 スキップ WHERE句で対象プレフィックスだけに限定
図1:外部テーブルのクエリ経路。パーティション列(METADATA$FILENAMEから導出)で対象プレフィックスだけを走査し、S3上のParquetを直接読む。

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)。

現場のコツ:検証環境で、パーティション列を定義しないまま日付別JSONの山を外部テーブル化したところ、WHERE句で日付を絞ってもファイル一覧の全走査が発生し、ウェアハウス時間を無駄に消費すると分かりました。本番ではS3を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購読権限を渡す形になります。

現場のコツ:検証段階で、AUTO_REFRESHを切って定期的な手動REFRESHに頼る構成を試したところ、オブジェクト数の多いプレフィックスでは更新のたびに広範なリスト処理が走り、鮮度の遅延とコストが読みにくくなると分かりました。本番ではS3イベント通知+AUTO_REFRESH=TRUEで新規ファイルの差分反映に寄せ、鮮度と負荷を両立させています。EMWでは重大障害0を継続しており、この種の落とし穴は検証で先に踏み抜く運用を徹底しています。

一点、仕様上の注意として、前述のPARTITION_TYPE = USER_SPECIFIEDを使う外部テーブルではAUTO_REFRESHはサポートされません。手動管理を選ぶなら、パーティション追加とREFRESHの運用フローをセットで設計しておく必要があります。

05ロードとの使い分け:性能特性とマテビュー

ここが最も判断を誤りやすいポイントです。外部テーブルは便利ですが、内部テーブルと同じ速度は出ません。マイクロパーティション統計やクラスタリングの恩恵がなく、実体はS3上のファイルを読みに行くため、繰り返し叩かれるダッシュボードのバックエンドには向きません。目安として、探索・一時分析・アーカイブ参照は外部テーブル、反復する本番クエリはロードが基本線です。どうしても外部テーブル上のホットなクエリを速くしたい場合は、Enterprise Edition以上で外部テーブルにマテリアライズドビューを張る手があります。マテビューが結果を保持することで、下地の外部テーブルへ都度クエリするより高速になります。

内部テーブル(ロード) 保管 Snowflake内部 書込 フルDML可 速度 最速(統計あり) 用途 反復する本番クエリ External Tables 保管 自社S3のまま 書込 読み取り専用 速度 枝刈り次第で中〜低 用途 探索・一時分析 Iceberg Tables 保管 自社S3(Parquet) 書込 読み書き(方式次第) 速度 高(統計・snapshot) 用途 オープン基盤・共有
図2:内部テーブル・External Tables・Iceberg Tablesの性格の違い。S3に置いたまま高速に扱いたいなら、外部テーブルよりIcebergが第一候補になりつつある。

06Iceberg Tablesという正常進化

「S3にデータを置いたまま扱いたい」という動機は、いま多くのケースでApache Iceberg Tablesに向かっています。外部テーブルが読み取り専用でSnowflake独自の枠組みだったのに対し、Icebergはオープンなテーブルフォーマットで、ACIDトランザクション・スキーマ進化・スナップショットを備え、Parquetのデータファイルとマニフェストで構成されます。S3への接続には、外部テーブルのストレージ統合に相当する外部ボリューム(External Volume)を作成し、そこにIAMの接続情報を持たせます。運用形態は大きく二つで、Snowflakeがカタログを持つSnowflake管理では読み書き・コンパクションなどのメンテナンスまでフル機能が使え、AWS Glueなどの外部カタログと統合する形では、他エンジンとの相互運用性を取りつつSnowflakeはおもにReadを担います。

現場のコツ:外部ボリュームの検証で、バケット名にドットを含むS3を指定すると構成できないと分かりました(SnowflakeがHTTPSの仮想ホスト形式でアクセスするため)。本番のバケット命名規約からドットを外すことで、後戻りを未然に防いでいます。単に「S3を読む」だけなら外部テーブル、「S3に置いたまま高速に読み書きし、将来的に他エンジンとも共有したい」ならIceberg、と切り分けるのが実務の目安です。

07まとめ:現場の判断基準

外部テーブルは「ロードしないで読む」ための強力な道具ですが、内部テーブルの代替ではありません。判断の軸は三つに整理できます。第一に、S3レイアウトを日付などのプレフィックスで設計し、METADATA$FILENAMEからパーティション列を切り出して枝刈りを効かせること。第二に、メタデータの鮮度はAUTO_REFRESH+S3イベント通知で差分反映に寄せ、手動REFRESHの全走査リスクを避けること。第三に、探索・アーカイブは外部テーブル、反復する本番クエリはロード、S3に置いたまま高速に扱いたいならIcebergへ、という使い分けです。いずれもSnowflakeがAWS上で動く前提を活かし、IAM・PrivateLink・KMS・SQSといったAWS側の設計とセットで組むことで、性能とコストと鮮度のバランスが初めて取れます。

参考情報(一次情報)

EMWはAWS×Snowflakeで、S3レイアウト設計から外部テーブル・Iceberg基盤の構築・運用までワンストップでご支援します。まずはお気軽にご相談ください。

相談する
← ブログ一覧へ戻る