

# 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 자정으로 지정됩니다.

**참고**  
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` 예에서는 날짜와 시간을 구분합니다. SQL에서는 `date`가 예약어이기 때문에 이 예제에서는 날짜를 나타내는 파티션 키의 이름으로 `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 \$1 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>

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

## 날짜 파티션 키에 DATE 형식 사용
<a name="partition-projection-kinesis-firehose-example-iso-formatted-dates"></a>

`day` 파티션 키의 값은 ISO 형식이므로 다음 예와 같이 날짜 파티션 키에 `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 키를 생성하는 것으로 가정합니다. `yyyy/MM/dd/HH`의 Firehose 기본 형식을 사용하는 경우 다음 예제와 같이 해당 테이블 속성이 `date` 유형이더라도 파티션 키를 `string` 유형으로 지정해야 합니다.  

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