🪣

SnowflakeでAWS S3 Express One Zoneを使うとどれだけ速いのか

2024/01/13に公開

SnowflakeでAWS S3 Express One Zoneを組み合わせて、パフォーマンスと互換性を検証したので結果を共有する。
互換性テストが通らなくても、一部の機能は使用できるようだ。

結論

読み取り系のワークロードでは、最大16%ほどのクエリパフォーマンスの改善が見られた
ただし、現時点では、スタンダードなS3バケットからExpress One Zoneへ移行する必要はない
現時点では移行するメリットをデメリットが上回る。
まず、書き込み系の操作はエラーで実行できない
また、LISTなどバケット全体のスキャンを行うクエリでは、最大20倍も遅くなった。

全体的にSnowflakeの内部のコードがExpress One Zoneを想定していないようでエラーが頻発した。 未サポートなので当然だが日常的な使用は厳しい。

SnowflakeでExpress One Zoneを活用した高速なデータレイクの構築を行うには、公式からサポートがアナウンスされるまでまだ待つ必要があると思われる。

意外なことに公式テストケースで互換性テストが失敗する原因となったMD5チェックサムgetBucketLocationの未サポートは重大な問題ではないように見えた。

以下に検証の詳細を記す。

Express One Zone外部ステージで実行できる操作と実行できない操作

Express One Zone外部ステージにどの操作が実行可能なのかを検証した。
ステージに書き込む系の処理はエラーになってしまった。

ステージに対して実行できた操作と、実行できなかった操作の一覧。△は実行可能だが非常に遅い。

コマンド 実行可能か
外部ステージへのクエリ
外部テーブルの作成
LISTコマンド
外部ステージからのロード
REMOVEコマンド
外部ステージへのアンロード
SnowpipeからのAuto Ingest
SnowpipeからのREST API Ingest

成功したこと

外部ステージへのクエリ

ほぼ普通にかける。プレフィックスは/で終わることに注意。

SELECT $1  FROM  @express_onezone/myfolder/(
   FILE_FORMAT => 'my_parquet_format', 
   PATTERN => '.*.parquet'
)

外部テーブルの作成

外部テーブル作成も可能。 metadata$filenameなどのメタデータ列も通常のバケットと同様に使えた。

CREATE EXTERNAL TABLE EXPRESS_EXTERNAL_TABLE (
   ...
   _LOAD_AT TIMESTAMP_NTZ AS (metadata$start_scan_time::timestamp_ntz),
)
    location = @express_onezone/myfolder/
    file_format='my_parquet'
    ;

LISTコマンド

LIST @express_onezone/my_directory/;

COPY INTO TABLE FROM [STAGE]

SQLは省略するが、データのロードも通常通り可能であった。

失敗した操作

Express One Zoneへのアンロード

普通にアンロードはできなさそう。
このバケットはデリミタで終わらないプレフィックスをサポートしていません。

COPY INTO @express_onezone/mydata.csv
FROM mytable
FILE_FORMAT = (TYPE = 'CSV');

SINGLE指定してもだめ。
Internal error accessing stage area:Internal error: java.lang.IllegalArgumentException: Cannot create enum from EXPRESS_ONEZONE value!

COPY INTO @express_onezone/mydata.csv
FROM my_table
FILE_FORMAT = (TYPE = 'CSV')
SINGLE=TRUE;

SnowpipeからのAuto Ingest

不可能。
Express One ZoneではマネージドなSQSへの通知の仕組みを見つけられなかった。
Auto IngestではなくSnowpipe REST APIを介したIngestは可能。

読み込み速度の検証

書き込みは検証できなかったので、読み込み系のクエリの実行速度を検証した。
読み込みのパフォーマンスでは約16%高速であった。

ただしLISTがやたら遅い。COPY INTOを行う時にもListing external files...でかなり待つ必要がある。

コマンド 通常のバケット Express One Zone
外部テーブルへのクエリ(5千万件) 4分45秒 4分16秒
LISTコマンド 22秒 8分30秒
Express One Zoneからのロード 44秒(Listing external files...) + 5分56秒(LOAD) 8分46秒(Listing external files...) + 4分57秒(LOAD)

検証時の条件

  • 同一のフォルダ構成を持つバケット同士で比較した。
  • 約15万個のparquetファイルが入っている
  • 全体のデータ量は約250GB。
  • 行数は約30億行。
  • 各ファイルはそれぞれ15~100MB。
  • ウェアハウスサイズは2x-Largeで行った。
  • root_bucket/yyyy/dd/mm/data.parquetのような階層で格納されている。

Express One Zoneを用いた外部ステージの作成手順

いつか常用できるようになったときのために手順を残しておく。

Express One Zoneのステージを作成

AWSの権限に注意。s3:*ではなく、s3express:*への許可が必要。

CREATE OR REPLACE TEMPORARY STAGE express_onezone
  URL = 's3compat://xxxxxx--apne1-az4--x-s3/'
  ENDPOINT='s3express-apne1-az4.ap-northeast-1.amazonaws.com'
  CREDENTIALS = (AWS_KEY_ID = 'xxxxxxxxxxx' AWS_SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxx');

以前はサポートにエンドポイントを追加してもらう必要があったはずだが、なぜか許可なしでも作れた。

S3のファイルをExpress OneZoneにコピー

aws syncコマンドで既存のバケットのコピーを作成した。

aws configure set default.s3.max_concurrent_requests 100
aws s3 sync s3://source_backet s3://xxxx--apne1-az4-x-s3

通常通りの操作を行う

SELECT $1  FROM  @express_onezone/myfolder/(
   FILE_FORMAT => 'my_parquet_format', 
   PATTERN => '.*.parquet'
);

追記

検証後にAWSからListBucketオペレーションだけで134ドルになる請求があってから気づいたが、ListBucketの呼び出し回数がとんでもないことになっていた。
0.0025USD/1000リクエストなので53万回のListBucketが呼び出されたようだ。LISTコマンドが遅かったのはディレクトリごとに再帰的にLISTが走っていたからという可能性がある。正式に対応するまでは、Express One Zoneで遊ぶのもほどほどにしたほうが良いかもしれない。

まとめ

まだ常用は厳しそうだが、今後に期待したい。

Snowflake Data Heroes

Discussion