

# Amazon Data Firehose 例
<a name="partition-projection-kinesis-firehose-example"></a>

Firehose を使用して Amazon S3 にデータを配信する場合、デフォルト設定は、次の例にあるようなキーを持つオブジェクトを書き込みます。

```
s3://amzn-s3-demo-bucket/prefix/yyyy/MM/dd/HH/file.extension
```

新しいデータが到着したときにパーティションを AWS Glue Data Catalog に追加する必要なく、クエリ時にパーティションを自動的に検索する Athena テーブルを作成するには、パーティション射影を使用できます。

以下の `CREATE TABLE` 例は、デフォルトの Firehose 設定を使用しています。

```
CREATE EXTERNAL TABLE my_ingested_data (
 ...
)
...
PARTITIONED BY (
 datehour STRING
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
 "projection.enabled" = "true",
 "projection.datehour.type" = "date",
 "projection.datehour.format" = "yyyy/MM/dd/HH",
 "projection.datehour.range" = "2021/01/01/00,NOW",
 "projection.datehour.interval" = "1",
 "projection.datehour.interval.unit" = "HOURS",
 "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${datehour}/"
)
```

`CREATE TABLE` ステートメントの `TBLPROPERTIES` 句は、Athena に次のように指定します。
+ テーブルのクエリ時にパーティション射影を使用する
+ パーティションキー `datehour` は `date` 型である (オプションで時刻を含む)
+ 日付の書式設定方法
+ 日付時刻の範囲。値はハイフンではなくカンマで区切る必要があることに注意してください。
+ Amazon S3 でのデータの検索先。

テーブルをクエリすると、Athena は `datehour` の値を計算し、ストレージロケーションテンプレートを使用して、パーティションの場所のリストを生成します。

**Topics**
+ [`date` タイプの使用方法](partition-projection-kinesis-firehose-example-using-the-date-type.md)
+ [パーティションキーの選択方法](partition-projection-kinesis-firehose-example-choosing-partition-keys.md)
+ [カスタムプレフィックスと動的パーティショニングの使用方法](partition-projection-kinesis-firehose-example-using-custom-prefixes-and-dynamic-partitioning.md)

# `date` タイプの使用方法
<a name="partition-projection-kinesis-firehose-example-using-the-date-type"></a>

射影パーティションキーに `date` 型を使用する場合、範囲を指定する必要があります。Firehose 配信ストリームが作成される前の日付に関するデータがないため、作成日を開始点として使用できます。また、将来の日付のデータがないため、最後として `NOW` という特別なトークンを使用できます。

`CREATE TABLE` の例では、開始日は 2021 年 1 月 1 日 UTC 午前 0 時と指定されています。

**注記**  
Athena が既存のパーティションのみを検索できるように、可能な限りデータと一致する範囲を設定します。

サンプルテーブルでクエリを実行すると、Athena は、`datehour`パーティションキーの条件を、値を生成する範囲と組み合わせて使用します。次のクエリについて考えます。

```
SELECT *
FROM my_ingested_data
WHERE datehour >= '2020/12/15/00'
AND datehour < '2021/02/03/15'
```

`SELECT` クエリの最初の条件では、`CREATE TABLE` ステートメントで指定された日付範囲の開始前の日付を使用しています。パーティション射影の設定では 2021 年 1 月 1 日より前の日付にはパーティションが指定されていないため、Athena は次の場所でのみデータを検索し、クエリ内のそれ以前の日付を無視します。

```
s3://amzn-s3-demo-bucket/prefix/2021/01/01/00/
s3://amzn-s3-demo-bucket/prefix/2021/01/01/01/
s3://amzn-s3-demo-bucket/prefix/2021/01/01/02/
...
s3://amzn-s3-demo-bucket/prefix/2021/02/03/12/
s3://amzn-s3-demo-bucket/prefix/2021/02/03/13/
s3://amzn-s3-demo-bucket/prefix/2021/02/03/14/
```

同様に、クエリが 2021 年 2 月 3 日 15:00 より前の日付と時刻で実行された場合、最後のパーティションに反映されているのは、クエリ条件の日時ではなく、現在の日付と時刻です。

最新のデータをクエリする場合は、Athena が将来の日付を生成しないという事実を活用し、次の例のように、開始 `datehour` のみを指定することができます。

```
SELECT *
FROM my_ingested_data
WHERE datehour >= '2021/11/09/00'
```

# パーティションキーの選択方法
<a name="partition-projection-kinesis-firehose-example-choosing-partition-keys"></a>

パーティション射影でパーティションの場所をパーティションキーにマッピングする方法を指定できます。前のセクションの `CREATE TABLE` の例では、日付と時刻を datehour という 1 つのパーティションキーにまとめましたが、他のスキームも可能です。例えば、パーティションキーを year、month、day、hour に分けてテーブルを構成することもできます。

ただし、日付を年、月、日に分割すると、`date` パーティション投影タイプは使用できなくなります。別の方法として、日付と時間を分離して `date` パーティション投影タイプを引き続き活用する方法がありますが、時間の範囲を指定するクエリは読みやすくします。

それを考慮して、次の `CREATE TABLE` の例では、日付と hour を分けています。`date` は SQL の予約語であるため、この例では日付を表すパーティションキーの名前として `day` を使用します。

```
CREATE EXTERNAL TABLE my_ingested_data2 (
 ...
)
...
PARTITIONED BY (
 day STRING,
 hour INT
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
 "projection.enabled" = "true",
 "projection.day.type" = "date",
 "projection.day.format" = "yyyy/MM/dd",
 "projection.day.range" = "2021/01/01,NOW",
 "projection.day.interval" = "1",
 "projection.day.interval.unit" = "DAYS",
 "projection.hour.type" = "integer",
 "projection.hour.range" = "0,23",
 "projection.hour.digits" = "2",
 "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${day}/${hour}/"
)
```

`CREATE TABLE` ステートメントの例では、hour は独立したパーティションキーで、整数に設定されています。hour パーティションキーの設定では、0～23 の範囲が指定され、Athena がパーティションの場所を生成するときに、hour を 2 桁でフォーマットする必要があります。

`my_ingested_data2` テーブルのクエリは次の例のようになります。

```
SELECT *
FROM my_ingested_data2
WHERE day = '2021/11/09'
AND hour > 3
```

## パーティションキーとパーティション射影データ型を理解する
<a name="partition-projection-kinesis-firehose-example-partition-key-types-and-partition-projection-types"></a>

最初の `CREATE TABLE` の例の `datehour` キーは、パーティション射影の設定では `date` として設定されていますが、パーティションキーの型は `string` なので、注意してください。2 番目の例の `day` についても同様です。パーティション射影に設定されている型は、Athena がパーティションの場所を生成するときの値のフォーマット方法のみを指示します。指定する型によって、パーティションキーの型は変更されません。クエリでは、`datehour` と `day` は `string` 型です。

クエリに `day = '2021/11/09'` のような条件が含まれている場合、Athena はパーティション射影設定で指定された日付形式を使用して、式の右辺の文字列を解析します。Athena は、日付が設定された範囲内であることを確認した後、日付形式を再び使用して日付を文字列として保存場所テンプレートに挿入します。

同様に、`day > '2021/11/09'` のようなクエリ条件の場合、Athena は右辺を解析し、設定された範囲内で一致するすべての日付のリストを生成します。次に、日付形式を使用して各日付を保存場所テンプレートに挿入し、パーティションの場所のリストを作成します。

`day > '2021-11-09'` や `day > DATE '2021-11-09'` と同じ条件を書くと動作しません。最初のケースでは、日付形式が一致せず (スラッシュではなくハイフンになっていることに注意してください)、2 番目のケースでは、データ型が一致しません。

# カスタムプレフィックスと動的パーティショニングの使用方法
<a name="partition-projection-kinesis-firehose-example-using-custom-prefixes-and-dynamic-partitioning"></a>

Firehose は、[カスタムプレフィックス](https://docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html)と[動的パーティショニング](https://docs.aws.amazon.com/firehose/latest/dev/dynamic-partitioning.html)を使用して設定できます。これらの機能を使用して、Amazon S3 キーを設定し、ユースケースをより適切にサポートするパーティション化スキームを設定できます。また、これらのパーティション化スキームでパーティション射影を使用し、それに応じて設定することもできます。

例えば、カスタムプレフィックス機能を使用して、デフォルトの `yyyy/MM/dd/HH` スキームではなく、ISO 形式の日付を持つ Amazon S3 キーを取得できます。

以下の例にあるように、カスタムプレフィックスと動的パーティショニングを組み合わせて、Firehose メッセージから `customer_id` のようなプロパティを抽出することもできます。

```
prefix/!{timestamp:yyyy}-!{timestamp:MM}-!{timestamp:dd}/!{partitionKeyFromQuery:customer_id}/
```

Amazon S3 プレフィックスを使用すると、Firehose 配信ストリームは、`s3://amzn-s3-demo-bucket/prefix/2021-11-01/customer-1234/file.extension` などのキーにオブジェクトを書き込みます。`customer_id` のようなプロパティの場合、事前に値が分かっていない場合もあるので、パーティション射影型 `injected` を使用し、次のような `CREATE TABLE` ステートメントを使用できます。

```
CREATE EXTERNAL TABLE my_ingested_data3 (
 ...
)
...
PARTITIONED BY (
 day STRING,
 customer_id STRING
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
 "projection.enabled" = "true",
 "projection.day.type" = "date",
 "projection.day.format" = "yyyy-MM-dd",
 "projection.day.range" = "2021-01-01,NOW",
 "projection.day.interval" = "1",
 "projection.day.interval.unit" = "DAYS",
 "projection.customer_id.type" = "injected",
 "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${day}/${customer_id}/"
)
```

`injected` 型のパーティションキーを持つテーブルに対してクエリを実行する場合、クエリにそのパーティションキーの値を含める必要があります。`my_ingested_data3` テーブルのクエリは次の例のようになります。

```
SELECT *
FROM my_ingested_data3
WHERE day BETWEEN '2021-11-01' AND '2021-11-30'
AND customer_id = 'customer-1234'
```

## day パーティションキーに DATE タイプを使用する
<a name="partition-projection-kinesis-firehose-example-iso-formatted-dates"></a>

`day` パーティションキーの値は ISO フォーマットされているので、次の例のように、day パーティションキーに、`STRING` ではなく、`DATE` 型を使用することもできます。

```
PARTITIONED BY (day DATE, customer_id STRING)
```

クエリを実行するとき、この戦略では、次の例のように、解析やキャストを行わずに、パーティションキーで日付関数を使用できます。

```
SELECT *
FROM my_ingested_data3
WHERE day > CURRENT_DATE - INTERVAL '7' DAY
AND customer_id = 'customer-1234'
```

**注記**  
`DATE` 型のパーティションキーを指定するには、[カスタムプレフィックス](https://docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html)機能を使用して ISO 形式の日付を含む Amazon S3 キーを作成したことを前提としています。デフォルトの Firehose 形式、`yyyy/MM/dd/HH` を使用している場合は、以下の例にあるように、対応するテーブルプロパティが `date` 型であっても、パーティションキーを `string` 型として指定する必要があります。  

```
PARTITIONED BY ( 
  `mydate` string)
TBLPROPERTIES (
  'projection.enabled'='true', 
   ...
  'projection.mydate.type'='date',
  'storage.location.template'='s3://amzn-s3-demo-bucket/prefix/${mydate}')
```