

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 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
```

若要建立 Athena 資料表，在查詢時間自動尋找分割區，而不必在新資料送達 AWS Glue Data Catalog 時將其新增至 ，您可以使用分割區投影。

下列 `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` 範例中，開始日期指定為世界協調時間 (UTC) 2021 年 1 月 1 日午夜。

**注意**  
設定與您的資料盡可能相符的範圍，以便 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 的分割區索引鍵，但也可以使用其他結構描述。例如，您也可以針對年份、月份、日期及小時，設定個別分割區索引鍵的資料表。

但是，將日期分割為年、月和日，表示無法使用 `date` 分割區投影類型。另一種方法是將日期與小時分開，即可仍然利用 `date` 分割區投影類型，但讓指定小時範圍的查詢更易於閱讀。

請記住，以下 `CREATE TABLE` 範例將日期與小時分開。由於 `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` 陳述式中，小時是個別的分割區索引鍵並設定為整數。小時分割區索引鍵的組態會指定範圍 0 到 23，而當 Athena 產生分割區位置時，小時應該格式化為兩位數。

對 `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`。第二個範例中的 `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'` 相同的條件不起作用。在第一種情況下，日期格式不相符 (請注意連字號而不是正斜線)，而在第二種情況下，資料類型不相符。

# 如何使用自訂字首和動態分割
<a name="partition-projection-kinesis-firehose-example-using-custom-prefixes-and-dynamic-partitioning"></a>

可以使用[自訂字首](https://docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html)和[動態分割](https://docs.aws.amazon.com/firehose/latest/dev/dynamic-partitioning.html)設定 Firehose。使用這些功能，您可以設定 Amazon S3 索引鍵，並設定能對您使用案例提供更佳支援的分割區結構描述。您還可以將分割區投影與這些分割結構描述搭配使用並相應地設定它們。

例如，您可以使用自訂字首功能來取得具有 ISO 格式化日期的 Amazon S3 索引鍵，而不是預設 `yyyy/MM/dd/HH` 結構描述。

您還可以將自訂字首與動態分割結合，從 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'
```

## 使用 DATE 類型作為日期分割區索引鍵
<a name="partition-projection-kinesis-firehose-example-iso-formatted-dates"></a>

因為 `day` 分割區索引鍵的值是 ISO 格式化，所以您也可以使用 `DATE` 類型而不是 `STRING` 來做為日期分割區索引鍵，如下列範例所示：

```
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}')
```