

# パーティションインデックスの作成
<a name="partition-indexes"></a>

時間の経過とともに、数十万のパーティションがテーブルに追加されます。[GetPartitions API](https://docs.aws.amazon.com/glue/latest/webapi/API_GetPartitions.html) は、テーブル内のパーティションをフェッチするために使用されます。この API は、リクエストで指定された式と一致するパーティションを返します。

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

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

**Topics**
+ [パーティションインデックスについて](#partition-index-1)
+ [パーティションインデックスを持つテーブルの作成](#partition-index-creating-table)
+ [パーティションインデックスの既存テーブルへの追加](#partition-index-existing-table)
+ [テーブル上のパーティションインデックスの説明](#partition-index-describing)
+ [パーティションインデックスの使用に関する制限事項](#partition-index-limitations)
+ [GetPartitions 呼び出しを最適化するためのインデックスの使用](#partition-index-getpartitions)
+ [エンジンとの統合](#partition-index-integration-engines)

## パーティションインデックスについて
<a name="partition-index-1"></a>

パーティションインデックスを作成する際、指定したテーブルに既に存在するパーティションキーのリストを指定します。パーティションインデックスは、テーブルで定義されているパーティションキーのサブリストです。パーティションインデックスは、テーブルで定義されたパーティションキーを任意の順序にして作成できます。上記の sales\$1data テーブルでは、可能なインデックスには (国、カテゴリ、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\$1n」個のパーティションインデックス項目になります。各パーティションインデックス項目は、現在のデータカタログストレージの AWS Glue 料金ポリシーに従って課金されます。ストレージオブジェクトの料金の詳細については、「[AWS Glue の料金](https://aws.amazon.com/glue/pricing/)」を参照してください。

## パーティションインデックスを持つテーブルの作成
<a name="partition-index-creating-table"></a>

テーブルの作成中にパーティションインデックスを作成できます。`CreateTable` リクエストは、[`PartitionIndex` オブジェクト](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-catalog-tables.html#aws-glue-api-catalog-tables-PartitionIndex)のリストを入力として指定します。1 つのテーブルには、最大 3 つのパーティションインデックスを作成できます。各パーティションインデックスには、テーブルに対して定義された名前と `partitionKeys` のリストが必要です。テーブル上に作成されたインデックスは、[`GetPartitionIndexes` API](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-catalog-tables.html#aws-glue-api-catalog-tables-GetPartitionIndexes) を使用してフェッチできます。

## パーティションインデックスの既存テーブルへの追加
<a name="partition-index-existing-table"></a>

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

追加されたパーティションのインデックスステータスが CREATING に設定され、インデックスデータの作成が開始されます。インデックスの作成プロセスが正常に終了すると、indexStatus は ACTIVE に更新され、プロセスが正常に終了しなかった場合、インデックスステータスは FAILED に更新されます。インデックスが作成できない理由は、複数あり得ます。`GetPartitionIndexes` オペレーションを使用して、障害の詳細を取得できます。考えられる障害は次のとおりです。
+ ENCRYPTED\$1PARTITION\$1ERROR – 暗号化されたパーティションを持つテーブルでのインデックスの作成はサポートされていません。
+ INVALID\$1PARTITION\$1TYPE\$1DATA\$1ERROR – `partitionKey` の値が対応する `partitionKey` データ型に対して有効な値でない場合に発生します。例えば、「int」データ型の `partitionKey` の値が「foo」の場合などです。
+ MISSING\$1PARTITION\$1VALUE\$1ERROR – `indexedKey` の `partitionValue` がない場合に発生します。これは、テーブルのパーティション化に整合性がない場合に発生します。
+ UNSUPPORTED\$1PARTITION\$1CHARACTER\$1ERROR – インデックス付きパーティションキーの値に「\$1u0000」、「\$1u0001」、または「\$1u0002」という文字が含まれている場合に発生します。
+ INTERNAL\$1ERROR – インデックスの作成中に内部エラーが発生しました。

## テーブル上のパーティションインデックスの説明
<a name="partition-index-describing"></a>

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

パーティションインデックスの `IndexStatus` は、次のいずれかになります。
+ `CREATING` – インデックスは現在作成されていますが、まだ使用することはできません。
+ `ACTIVE` – インデックスは、すぐに使用できます。リクエストにインデックスを使用して最適化されたクエリを実行できます。
+ `DELETING` – インデックスは現在削除されているため、使用できなくなっています。アクティブ状態のインデックスは、`DeletePartitionIndex` リクエストを使用してステータスを ACTIVE から DELETING に移行することによって削除できます。
+ `FAILED` – 既存のテーブルでインデックスの作成に失敗しました。失敗したインデックスは、直近の 10 個まで各テーブルに保存されます。

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

## パーティションインデックスの使用に関する制限事項
<a name="partition-index-limitations"></a>

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

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

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

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

## GetPartitions 呼び出しを最適化するためのインデックスの使用
<a name="partition-index-getpartitions"></a>

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

上記の *sales\$1data* テーブルには、[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"」に該当するすべてのパーティションをフェッチしたら、カテゴリの式にフィルタリングが実行されます。  | 

## エンジンとの統合
<a name="partition-index-integration-engines"></a>

Redshift Spectrum、Amazon EMR、および AWS Glue ETL Spark DataFrames は、インデックスが AWS Glue で ACTIVE 状態になった後にパーティションを取得するためにインデックスを利用できます。[Athena](https://docs.aws.amazon.com/athena/latest/ug/glue-best-practices.html#glue-best-practices-partition-index) と [AWS Glue ETL DynamicFrame](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-partitions.html#aws-glue-programming-etl-partitions-cat-predicates) では、クエリを向上させるためにインデックスを利用するには追加のステップに従う必要があります。

### パーティションのフィルタリングの有効化
<a name="enable-partition-filtering-athena"></a>

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

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

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

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

1. **[テーブルのプロパティ]** で、次の内容を追加します。
   + キー – `partition_filtering.enabled`
   + 値 – `true`

1. **[Apply]** (適用) を選択します。

または、Athena で [ALTER TABLE SET PROPERTIES](https://docs.aws.amazon.com/athena/latest/ug/alter-table-set-tblproperties.html) クエリを実行してこのパラメータを設定することもできます。

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