Amazon Web Services ブログ
新機能: sort コンパクションと z-order コンパクションで Amazon S3 内での Apache Iceberg クエリパフォーマンスを向上
sort
コンパクションと z-order
コンパクションを使用して、Amazon S3 Tables と 汎用 S3 バケットでの Apache Iceberg クエリパフォーマンスを向上させることが可能になりました。
通常、Iceberg は AWS Glue データカタログや S3 Tables で Amazon Simple Storage Service (Amazon S3) 内の大規模な分析データセットを管理するために使用します。Iceberg テーブルは、同時ストリーミングやバッチインジェスト、スキーマ進化、タイムトラベルなどのユースケースをサポートします。高インジェストまたは頻繁に更新されるデータセットを扱うときは、データレイクに多数の小さなファイルが蓄積される場合があり、クエリのコストやパフォーマンスに影響を及ぼします。皆さんからは、Iceberg のデータレイアウトの最適化は操作が複雑で、多くの場合にカスタムパイプラインの開発と維持が必要になるというご意見をいただいています。マネージドコンパクションでのデフォルトの binpack
戦略はパフォーマンスを大幅に向上させますが、S3 と S3 Tables の両方に sort
および z-order
のコンパクションオプションを導入すると、1 つ、または複数のディメンション全体をフィルタリングするクエリのパフォーマンスがさらに大きく向上します。
2 つの新しいコンパクション戦略: Sort
と z-order
データをより効率的に整理するため、Amazon S3 では、デフォルトの binpack
コンパクションに加えて、sort
と z-order
の 2 つの新しいコンパクション戦略がサポートされるようになりました。これらの高度な戦略は、AWS Glue データカタログによる最適化を通じて、フルマネージド型の S3 Tables と、汎用 S3 バケット内の Iceberg テーブルの両方で利用できます。
Sort
コンパクションは、ユーザー定義の列順序に基づいてファイルを整理します。テーブルにソート順序が定義されている場合、S3 Tables コンパクションはコンパクションプロセス時にそのソート順序を使用して、類似する値をクラスター化するようになります。これは、スキャンされるファイルの数を減らすことでクエリの実行効率性を向上させます。例えば、state
や zip_code
による sort
コンパクションでテーブルが整理されている場合、これらの列をフィルタリングするクエリでスキャンされるファイル数が減るため、レイテンシーとクエリエンジンコストが低減します。
Z-order
コンパクションは、複数のディメンション全体で効率的なファイルプルーニングを有効にすることで、ファイルをさらに整理します。この戦略は、複数の列からの値の二進数表現をソート可能な単一のスカラーにインターリーブするため、空間クエリや多次元クエリには特に有用です。例えば、ワークロードに pickup_location
、dropoff_location
、および fare_amount
で同時にフィルタリングするクエリが含まれる場合に z-order
コンパクションを使用すると、スキャンされるファイルの総数を従来のソートベースのレイアウトよりも少なくすることができます。
S3 Tables は、Iceberg テーブルのメタデータを使用して現行のソート順序を判断します。テーブルにソート順序が定義されている場合は、継続的なメンテナンス時に sort
コンパクションが自動的に適用されるため、アクティブ化するための追加設定は必要ありません。z-order
を使用するには、S3 Tables API を使用してテーブルのメンテナンス設定を更新し、戦略を z-order
に設定する必要があります。汎用 S3 バケット内の Iceberg テーブルの場合は、コンパクション設定を更新することで、最適化の最中に sort
または z-order
コンパクションを使用するように AWS Glue データカタログを設定できます。
sort
または z-order
の対象となるのは、これらを有効化した後で書き込まれた新しいデータのみです。コンパクション実施済みの既存ファイルは、テーブルのメンテナンス設定でターゲットファイルのサイズを大きくするか、標準の Iceberg ツールを使用してデータを書き換えることでファイルを明示的に書き換える場合を除き、そのまま変更されません。この動作は、いつ、どのくらいのデータを整理し直すかをユーザーが制御して、コストとパフォーマンスのバランスを取ることができるように設計されたものです。
実際の動作を見てみましょう
ここでは、Apache Spark と AWS コマンドラインインターフェイス (AWS CLI) を使用するシンプルな例を説明していきます。インストール済みの Spark クラスターと S3 テーブルバケットを用意しました。testnamespace
内には testtable
という名前のテーブルがあります。テーブルにデータを追加できるように、コンパクションを一時的に無効にしました。
データを追加したら、テーブルのファイル構造を確認します。
spark.sql("""
SELECT
substring_index(file_path, '/', -1) as file_name,
record_count,
file_size_in_bytes,
CAST(UNHEX(hex(lower_bounds[2])) AS STRING) as lower_bound_name,
CAST(UNHEX(hex(upper_bounds[2])) AS STRING) as upper_bound_name
FROM ice_catalog.testnamespace.testtable.files
ORDER BY file_name
""").show(20, false)
+--------------------------------------------------------------+------------+------------------+----------------+----------------+
|file_name |record_count|file_size_in_bytes|lower_bound_name|upper_bound_name|
+--------------------------------------------------------------+------------+------------------+----------------+----------------+
|00000-0-66a9c843-5a5c-407f-8da4-4da91c7f6ae2-0-00001.parquet |1 |837 |Quinn |Quinn |
|00000-1-b7fa2021-7f75-4aaf-9a24-9bdbb5dc08c9-0-00001.parquet |1 |824 |Tom |Tom |
|00000-10-00a96923-a8f4-41ba-a683-576490518561-0-00001.parquet |1 |838 |Ilene |Ilene |
|00000-104-2db9509d-245c-44d6-9055-8e97d4e44b01-0-00001.parquet|1000000 |4031668 |Anjali |Tom |
|00000-11-27f76097-28b2-42bc-b746-4359df83d8a1-0-00001.parquet |1 |838 |Henry |Henry |
|00000-114-6ff661ca-ba93-4238-8eab-7c5259c9ca08-0-00001.parquet|1000000 |4031788 |Anjali |Tom |
|00000-12-fd6798c0-9b5b-424f-af70-11775bf2a452-0-00001.parquet |1 |852 |Georgie |Georgie |
|00000-124-76090ac6-ae6b-4f4e-9284-b8a09f849360-0-00001.parquet|1000000 |4031740 |Anjali |Tom |
|00000-13-cb0dd5d0-4e28-47f5-9cc3-b8d2a71f5292-0-00001.parquet |1 |845 |Olivia |Olivia |
|00000-134-bf6ea649-7a0b-4833-8448-60faa5ebfdcd-0-00001.parquet|1000000 |4031718 |Anjali |Tom |
|00000-14-c7a02039-fc93-42e3-87b4-2dd5676d5b09-0-00001.parquet |1 |838 |Sarah |Sarah |
|00000-144-9b6d00c0-d4cf-4835-8286-ebfe2401e47a-0-00001.parquet|1000000 |4031663 |Anjali |Tom |
|00000-15-8138298d-923b-44f7-9bd6-90d9c0e9e4ed-0-00001.parquet |1 |831 |Brad |Brad |
|00000-155-9dea2d4f-fc98-418d-a504-6226eb0a5135-0-00001.parquet|1000000 |4031676 |Anjali |Tom |
|00000-16-ed37cf2d-4306-4036-98de-727c1fe4e0f9-0-00001.parquet |1 |830 |Brad |Brad |
|00000-166-b67929dc-f9c1-4579-b955-0d6ef6c604b2-0-00001.parquet|1000000 |4031729 |Anjali |Tom |
|00000-17-1011820e-ee25-4f7a-bd73-2843fb1c3150-0-00001.parquet |1 |830 |Noah |Noah |
|00000-177-14a9db71-56bb-4325-93b6-737136f5118d-0-00001.parquet|1000000 |4031778 |Anjali |Tom |
|00000-18-89cbb849-876a-441a-9ab0-8535b05cd222-0-00001.parquet |1 |838 |David |David |
|00000-188-6dc3dcca-ddc0-405e-aa0f-7de8637f993b-0-00001.parquet|1000000 |4031727 |Anjali |Tom |
+--------------------------------------------------------------+------------+------------------+----------------+----------------+
only showing top 20 rows
テーブルが複数の小さなファイルで構成されており、新しいファイルの上限値と下限値が重複していることがわかります。データは明らかにソートされていません。
テーブルのソート順序を設定します。
spark.sql("ALTER TABLE ice_catalog.testnamespace.testtable WRITE ORDERED BY name ASC")
テーブルコンパクションを有効にします (デフォルトで有効になっていますが、このデモの最初に無効化しました)。
aws s3tables put-table-maintenance-configuration --table-bucket-arn ${S3TABLE_BUCKET_ARN} --namespace testnamespace --name testtable --type icebergCompaction --value "status=enabled,settings={icebergCompaction={strategy=sort}}"
有効にしたら、次のコンパクションジョブがトリガーされるのを待ちます。十分な数の小さなファイルが存在する場合、ジョブは一日中実行されます。コンパクションステータスは、次のコマンドを使用して確認できます。
aws s3tables get-table-maintenance-job-status --table-bucket-arn ${S3TABLE_BUCKET_ARN} --namespace testnamespace --name testtable
コンパクションが完了したら、テーブルを構成するファイルをもう一度調べます。データが 2 つのファイルにコンパクションされており、上限値と下限値がこれら 2 つのファイル全体でデータがソートされたことを示しています。
spark.sql("""
SELECT
substring_index(file_path, '/', -1) as file_name,
record_count,
file_size_in_bytes,
CAST(UNHEX(hex(lower_bounds[2])) AS STRING) as lower_bound_name,
CAST(UNHEX(hex(upper_bounds[2])) AS STRING) as upper_bound_name
FROM ice_catalog.testnamespace.testtable.files
ORDER BY file_name
""").show(20, false)
+------------------------------------------------------------+------------+------------------+----------------+----------------+
|file_name |record_count|file_size_in_bytes|lower_bound_name|upper_bound_name|
+------------------------------------------------------------+------------+------------------+----------------+----------------+
|00000-4-51c7a4a8-194b-45c5-a815-a8c0e16e2115-0-00001.parquet|13195713 |50034921 |Anjali |Kelly |
|00001-5-51c7a4a8-194b-45c5-a815-a8c0e16e2115-0-00001.parquet|10804307 |40964156 |Liza |Tom |
+------------------------------------------------------------+------------+------------------+----------------+----------------+
ファイルの数が少なく、ファイルのサイズが大きくなっていて、指定したソート列全体でクラスタリングが改善されています。
z-order
の使用にも同じ手順を実行しますが、その場合はメンテナンス設定で strategy=z-order
を設定します。
利用可能なリージョン
Sort
コンパクションと z-order
コンパクションは、Amazon S3 Tables がサポートされるすべての AWS リージョンで利用でき、AWS Glue データカタログによる最適化が利用可能な汎用 S3 バケットにも利用できます。S3 Tables に関しては、既存の使用量とメンテナンス料金以外の追加料金はかかりません。データカタログによる最適化に関しては、コンパクション時にコンピューティング料金が適用されます。
これらの変更により、sort
列または z-order
列でフィルタリングするクエリは、より高速なクエリ時間とエンジンコストの削減からメリットを得られます。私の経験では、binpack
から sort
または z-order
に切り替えるときに、データレイアウトとクエリパターンに応じて、3 倍以上のパフォーマンス向上を確認できました。実際のデータでパフォーマンスがどれだけ向上したかをぜひ教えてください。
詳細については、Amazon S3 Tables の製品ページにアクセスするか、「S3 Tables のメンテナンス」ドキュメントをご覧ください。S3 Tables API または AWS Glue による最適化を使用して、今すぐ独自のテーブルで新しい戦略のテストを開始することも可能です。
原文はこちらです。