AWS Glue
開発者ガイド

AWS Glue での ETL 出力のパーティションの管理

パーティション分割は、データセットを整理して効率的にクエリを実行可能にする重要な手法です。1 つまたは複数の列の個別の値に基づいて、データを階層形式のディレクトリ構造に整理します。

たとえば、Amazon Simple Storage Service (Amazon S3) のアプリケーションログを年月日別の日付でパーティション分割できます。次に 1 日分のデータに対応するファイルを s3://my_bucket/logs/year=2018/month=01/day=23/ などのプレフィックス別に配置します。Amazon Athena、Amazon Redshift Spectrum、AWS Glue などのシステムでは、これらのパーティションを使用して、基になるすべてのデータを Amazon S3 から読み取ることなく、パーティション値でデータをフィルタできます。

クローラは、ファイルタイプとスキーマを推測するだけでなく、AWS Glue データカタログ を事前設定するときにデータセットのパーティション構造を自動的に識別します。その結果、パーティション列に対して AWS Glue ETL ジョブやクエリエンジン (Amazon Athena など) でクエリを実行できるようになります。

テーブルをクロールした後で、AWS Glue コンソールに移動して [View Partitions (パーティションの表示)] を選択すると、クローラで作成したパーティションを表示できます。

Apache Hive 形式のパーティション分割されたパス (key=val 形式) の場合、クローラはキー名を使用して自動的に列名を事前設定します。それ以外の場合は、partition_0partition_1 などのデフォルト名が使用されます。コンソールでデフォルト名を変更するには、テーブルに移動して [Edit Schema (スキーマの編集)] を選択し、パーティション列の名前を変更します。

次に、ETL スクリプトでパーティション列をフィルタリングできます。

プッシュダウン述語を使用した事前フィルタ処理

多くの場合、プッシュダウン述語を使用してパーティションをフィルタリングできます。データセットのすべてのファイルをリストアップして読み取る必要はありません。データセット全体を読み取って DynamicFrame でフィルタリングする代わりに、データカタログ でパーティションのメタデータに直接フィルタを適用できます。次に、実際に必要なものだけをリストアップして DynamicFrame 内に読み取ることができます。

たとえば、Python では以下のように記述できます。

glue_context.create_dynamic_frame.from_catalog( database = "my_S3_data_set", table_name = "catalog_data_table", push_down_predicate = my_partition_predicate)

これによって作成される DynamicFrame では、データカタログ のパーティションのうち、述語式を満たすものだけがロードされます。ロードするデータのサブセットを絞り込む度合いに応じて、処理時間を大幅に短縮できる場合があります。

述語式として、Spark SQL でサポートされている任意のブール式を使用できます。Spark SQL クエリで WHERE 句に指定できる条件は、すべて正常に動作します。たとえば、述語式 pushDownPredicate = "(year=='2017' and month=='04')" では、year が「2017」に等しく、month が「04」に等しい データカタログ のパーティションのみロードされます。詳細については、Apache Spark SQL のドキュメントを参照してください。特に Scala SQL 関数リファレンスが参考になります。

Hive 形式の Amazon S3 パスのパーティション分割に加えて、Apache Parquet および Apache ORC ファイル形式では、さらに各ファイルを列値を表すデータのブロック単位にパーティション分割します。各ブロックにも、ブロック内のレコードに関する統計情報 (列の最小/最大値など) が保存されます。AWS Glue は、Hive 形式のパーティションと、これらの形式のブロックパーティションの両方でプッシュダウン述語をサポートしています。これにより、Parquet 形式と ORC 形式で不要な Amazon S3 パーティションを取り除き、列統計を使用して不要と判断したブロックをスキップできます。

パーティションの書き込み

デフォルトでは、DynamicFrame は書き込むときにパーティション分割されません。すべての出力ファイルは、指定した出力パスの最上位レベルに書き込まれます。最近まで、DynamicFrame をパーティションに書き込む唯一の方法は、書き込む前に Spark SQL DataFrame に変換することでした。

ただし、DynamicFrames ではキーのシーケンスを使用したネイティブのパーティション分割がサポートされるようになりました。この場合、シンクの作成時に partitionKeys オプションを使用します。たとえば、次の Python コードではデータセットを Parquet 形式で Amazon S3 のディレクトリに書き込みます。これらのディレクトリは、タイプフィールドに従ってパーティション分割されています。そこから、他のシステム (Amazon Athena など) を使用して、これらのパーティションを処理できます。

glue_context.write_dynamic_frame.from_options( frame = projectedEvents, connection_type = "s3", connection_options = {"path": "$outpath", "partitionKeys": ["type"]}, format = "parquet")