パーティションインデックスの作成 - AWS Glue

パーティションインデックスの作成

時間の経過とともに、数十万のパーティションがテーブルに追加されます。GetPartitions API は、テーブル内のパーティションをフェッチするために使用されます。この API は、リクエストで指定された式と一致するパーティションを返します。

「国」、「カテゴリ」、「年」、「月」、「creationDate」のキーで分割された例として、sales_data テーブルを参考にします。2020 年の 2020 年 8 月 15 日以降に「書籍」のカテゴリで販売されたアイテムの売り上げデータを取得する場合、Data Catalog に「Category = 'Books' and creationDate > '2020-08-15'」という式で GetPartitions リクエストを行います。

テーブルにパーティションインデックスが存在しない場合、AWS Glue では、テーブルのすべてのパーティションがロードされ、GetPartitions リクエストでユーザーが指定したクエリ式を使用してロードされたパーティションがフィルタリングされます。インデックスのないテーブルでパーティション数が増えると、クエリの実行に時間がかかります。インデックスを使用すると、GetPartitions クエリでは、テーブル内のすべてのパーティションをロードするのではなく、パーティションのサブセットを取得しようとします。

パーティションインデックスについて

パーティションインデックスを作成する際、指定したテーブルに既に存在するパーティションキーのリストを指定します。パーティションインデックスは、テーブルで定義されているパーティションキーのサブリストです。パーティションインデックスは、テーブルで定義されたパーティションキーを任意の順序にして作成できます。上記の sales_data テーブルでは、可能なインデックスには (国、カテゴリ、creationDate)、(国、カテゴリ、年)、(国、カテゴリ)、(国)、(カテゴリ、国、年、月) などがあります。

Data Catalog は、インデックスの作成時に指定された順序でパーティション値を連結します。インデックスは、テーブルに追加されたパーティションと整合して構築されます。インデックスは文字列 (string、char、varchar)、数値 (int、bigint、long、tinyint、smallint)、日付 (yyyy-MM-dd) の列タイプに対して作成できます。

サポートされているデータ型

  • Date – YYYY-MM-DD などの ISO 形式の日付。たとえば、2020-08-15 の日付。この形式では、ハイフン (‐) を使用して年、月、日を区切ります。インデックス用の日付の許容範囲は、0000-01-01 から 9999-12-31 までです。

  • String – 一重引用符または二重引用符で囲まれた文字列リテラルです。

  • Char – char(10) など、1 から 255 までの指定された長さを持つ固定長の文字データです。

  • Varchar – varchar(10) など、1 から 65535 までの指定された長さを持つ可変長の文字データです。

  • Numeric — int、bigint、long、tinyint、smallint

「Numeric」、「String」、「Date」データ型のインデックスは、=、>、>=、<、<=、演算子間をサポートします。インデックス作成ソリューションは現在、AND 論理演算子のみをサポートしています。「LIKE」、「IN」、「OR」、および「NOT」の演算子のある部分式は、インデックスを使用してフィルタリングする場合、この式では無視されます。無視された部分式のフィルタリングは、インデックスフィルタリングを適用した後にフェッチされたパーティションに対して行われます。

テーブルに追加されたパーティションごとに、対応するインデックス項目が作成されます。「n」個のパーティションを持つテーブルの場合、1 つのパーティションインデックスは「n」個のパーティションインデックス項目になります。同じテーブルの「m」個のパーティションインデックスは、「m*n」個のパーティションインデックス項目になります。各パーティションインデックス項目は、現在のデータカタログストレージの AWS Glue 料金ポリシーに従って課金されます。ストレージオブジェクトの料金の詳細については、「AWS Glue の料金」を参照してください。

パーティションインデックスを持つテーブルの作成

テーブルの作成中にパーティションインデックスを作成できます。CreateTable リクエストは、PartitionIndex オブジェクトのリストを入力として指定します。1 つのテーブルには、最大 3 つのパーティションインデックスを作成できます。各パーティションインデックスには、テーブルに対して定義された名前と partitionKeys のリストが必要です。テーブル上に作成されたインデックスは、GetPartitionIndexes API を使用してフェッチできます。

パーティションインデックスの既存テーブルへの追加

既存のテーブルにパーティションインデックスを追加するには、CreatePartitionIndex オペレーションを使用します。CreatePartitionIndex オペレーションごとに、1 つの PartitionIndex を作成できます。インデックスを追加しても、テーブルの可用性には影響しません。これは、インデックスの作成中もテーブルが使用可能になるためです。

追加されたパーティションのインデックスステータスが CREATING に設定され、インデックスデータの作成が開始されます。インデックスの作成プロセスが正常に終了すると、indexStatus は ACTIVE に更新され、プロセスが正常に終了しなかった場合、インデックスステータスは FAILED に更新されます。インデックスが作成できない理由は、複数あり得ます。GetPartitionIndexes オペレーションを使用して、障害の詳細を取得できます。考えられる障害は次のとおりです。

  • ENCRYPTED_PARTITION_ERROR – 暗号化されたパーティションを持つテーブルでのインデックスの作成はサポートされていません。

  • INVALID_PARTITION_TYPE_DATA_ERROR – partitionKey の値が対応する partitionKey データ型に対して有効な値でない場合に発生します。例えば、「int」データ型の partitionKey の値が「foo」の場合などです。

  • MISSING_PARTITION_VALUE_ERROR – indexedKeypartitionValue がない場合に発生します。これは、テーブルのパーティション化に整合性がない場合に発生します。

  • UNSUPPORTED_PARTITION_CHARACTER_ERROR – インデックス付きパーティションキーの値に「\u0000」、「\u0001」、または「\u0002」という文字が含まれている場合に発生します。

  • INTERNAL_ERROR – インデックスの作成中に内部エラーが発生しました。

テーブル上のパーティションインデックスの説明

テーブル上に作成されたパーティションインデックスを取得するには、GetPartitionIndexes オペレーションを使用します。レスポンスとして、テーブル上のすべてのインデックスと、各インデックスの現在のステータス (IndexStatus) が返ります。

パーティションインデックスの IndexStatus は、次のいずれかになります。

  • CREATING – インデックスは現在作成されていますが、まだ使用することはできません。

  • ACTIVE – インデックスは、すぐに使用できます。リクエストにインデックスを使用して最適化されたクエリを実行できます。

  • DELETING – インデックスは現在削除されているため、使用できなくなっています。アクティブ状態のインデックスは、DeletePartitionIndex リクエストを使用してステータスを ACTIVE から DELETING に移行することによって削除できます。

  • FAILED – 既存のテーブルでインデックスの作成に失敗しました。失敗したインデックスは、直近の 10 個まで各テーブルに保存されます。

既存のテーブルで作成されたインデックスには、次のような状態遷移があり得ます。

  • CREATING → ACTIVE → DELETING

  • CREATING → FAILED

パーティションインデックスの使用に関する制限事項

パーティションインデックスを作成したら、テーブルとパーティションの機能に対する次の変更点に注意してください。

新規パーティションの作成 (インデックス追加後)

テーブルにパーティションインデックスが作成されると、テーブルに追加されたすべての新しいパーティションは、インデックス付きキーのデータ型チェックのために検証されます。インデックス付きキーのパーティション値は、データ型形式について検証されます。データ型のチェックが失敗すると、パーティションの作成操作は失敗します。sales_data テーブルに対して、キー (カテゴリ、年) のインデックスが作成され、カテゴリの型が string、年の型が int の場合、YEAR の値が「foo」であれば、新しいパーティションの作成は失敗します。

インデックスを有効にすると、U+0000、U+00001、U+0002 という文字を含むインデックス付きキー値のパーティションの追加が失敗するようになります。

テーブルの更新

テーブル上にパーティションインデックスを作成すると、既存のパーティションキーのパーティションキー名を変更することはできません。また、インデックスに登録されているキーのタイプまたは順序を変更することはできません。

GetPartitions 呼び出しを最適化するためのインデックスの使用

インデックス付きテーブルで GetPartitions を呼び出すとき、式を含めることができます。また、適用可能な場合は、Data Catalogで、可能であればインデックスが使用されます。インデックスの最初のキーは、フィルタリングに使用されるインデックスの式に含めて渡す必要があります。フィルタリングのインデックスの最適化は、ベストエフォートとして適用されます。Data Catalog では、可能な限りインデックスの最適化を使用しようとしますが、インデックスが見つからない場合、またはサポートされていない演算子の場合は、すべてのパーティションをロードする既存の実装に戻します。

上記の sales_data テーブルには、[Country, Category, Year] (国、カテゴリ、年) のインデックスを追加できます。式に「Country」が渡されない場合、登録されたインデックスは、インデックスを使用したパーティションのフィルタリングができません。最大 3 つのインデックスを追加して、さまざまなクエリパターンをサポートできます。

いくつかの式を例に取り、そこでインデックスが機能する様子を示します。

表現 インデックスの使用方法

Country = 'US'

インデックスは、パーティションをフィルタリングするために使用されます。

Country = 'US' and Category = 'Shoes'

インデックスは、パーティションをフィルタリングするために使用されます。

Category = 'Shoes'

式に「country」が指定されていないため、インデックスは使用されません。レスポンスを返すため、すべてのパーティションがロードされます。

Country = 'US' and Category = 'Shoes' and Year > '2018'

インデックスは、パーティションをフィルタリングするために使用されます。

Country = 'US' and Category = 'Shoes' and Year > '2018' and month = 2

インデックスを使用して、「country = "US" and category = "shoes" and year > 2018」に該当するすべてのパーティションがフェッチされます。その後、月に関する式によるフィルタリングが実行されます。

Country = 'US' AND Category = 'Shoes' OR Year > '2018'

OR 演算子が式に存在するため、インデックスは使用されません。

Country = 'US' AND Category = 'Shoes' AND (Year = 2017 OR Year = '2018')

インデックスを使用して、「country = "US" and category = "shoes"」に該当するのすべてのパーティションがフェッチされ、その後、年に関する式によるフィルタリングが実行されます。

Country in ('US', 'UK') AND Category = 'Shoes'

IN 演算子は現在サポートされていないため、インデックスはフィルタリングに使用されません。

Country = 'US' AND Category in ('Shoes', 'Books')

インデックスを使用して、「country = "US"」に該当するのすべてのパーティションが取得され、その後、カテゴリに関する式によるフィルタリングが実行されます。

Country = 'US' AND Category in ('Shoes', 'Books') AND (creationDate > '2023-9-01'

「creationDate > '2023-9-01'」に設定し、インデックスを使用して「country = "US"」に該当するすべてのパーティションをフェッチしたら、カテゴリの式にフィルタリングが実行されます。

エンジンとの統合

Redshift Spectrum、Amazon EMR、および AWS Glue ETL Spark DataFrames は、インデックスが AWS Glue で ACTIVE 状態になった後にパーティションを取得するためにインデックスを利用できます。AthenaAWS Glue ETL DynamicFrame では、クエリを向上させるためにインデックスを利用するには追加のステップに従う必要があります。

パーティションのフィルタリングの有効化

Athena でパーティションフィルタリングを有効にするには、テーブルのプロパティを次のように更新する必要があります。

  1. AWS Glue コンソールで、[データカタログ][テーブル] を選択します。

  2. テーブルを選択します。

  3. [アクション][テーブルの編集] を選択します。

  4. [テーブルのプロパティ] で、次の内容を追加します。

    • キー – partition_filtering.enabled

    • 値 – true

  5. [Apply] を選択します。

または、Athena で ALTER TABLE SET PROPERTIES クエリを実行してこのパラメータを設定することもできます。

ALTER TABLE partition_index.table_with_index SET TBLPROPERTIES ('partition_filtering.enabled' = 'true')