

# 데이터 파티셔닝
<a name="partitions"></a>

데이터를 분할하면 각 쿼리가 스캔하는 데이터의 양을 제한하여 성능을 향상시키고 비용을 절감할 수 있습니다. 어떤 키를 기준으로도 데이터를 분할할 수 있습니다. 일반적으로 시간을 기준으로 데이터가 분할되어, 다중 레벨 파티셔닝 체계가 형성되는 경우가 많습니다. 예를 들어, 매시간 데이터를 수집하는 고객은 연, 월, 일, 시를 기준으로 분할할 수 있습니다. 다양한 소스로부터 데이터를 수집하되 하루에 한 번만 로드하는 고객의 경우 데이터 원본 식별자 및 날짜별로 분할할 수 있습니다.

Athena는 Apache Hive 스타일 파티션을 사용할 수 있습니다. 이 파티션의 데이터 경로에 등호로 연결된 키 값 페어가 포함되어 있습니다(예: `country=us/...` 또는 `year=2021/month=01/day=26/...`). 따라서 경로에는 파티션 키의 이름과 각 경로가 나타내는 값이 모두 포함됩니다. 파티션을 나눈 테이블에 새 Hive 파티션을 로드하려면 [MSCK REPAIR TABLE](msck-repair-table.md) 명령을 사용할 수 있으며 이 명령은 Hive 스타일 파티션에서만 작동합니다.

Athena는 비 Hive 스타일 파티션 체계를 사용할 수도 있습니다. 예를 들어 CloudTrail 로그 및 Firehose 전송 스트림은 `data/2021/01/26/us/6fc7845e.json`와 같은 날짜 부분에 대해 별도의 경로 구성 요소를 사용합니다. Hive와 호환되지 않는 데이터의 경우 [ALTER TABLE ADD PARTITION](alter-table-add-partition.md)을(를) 사용하여 파티션을 수동으로 추가합니다.

## 고려 사항 및 제한 사항
<a name="partitions-considerations-limitations"></a>

파티셔닝을 사용할 때는 다음 사항에 유의하세요.
+ `WHERE` 절에서 분할된 테이블을 쿼리하고 파티션을 지정하면 Athena는 해당 파티션의 데이터만 검색합니다.
+ 객체가 많은 Amazon S3 버킷에 대해 쿼리를 실행하는데 데이터가 분할되지 않은 경우, 그러한 쿼리는 Amazon S3의 `GET` 요청 빈도 제한에 영향을 주고 Amazon S3 예외를 발생시킬 수 있습니다. 오류를 방지하려면 데이터를 분할하세요. 또한 Amazon S3 요청 빈도를 조정합니다. 자세한 내용은 [모범 사례 설계 패턴: Amazon S3 성능 최적화](https://docs.aws.amazon.com/AmazonS3/latest/userguide/request-rate-perf-considerations.html)를 참조하세요.
+ Athena에 사용될 파티션 위치는 `s3` 프로토콜(예: `s3://amzn-s3-demo-bucket/folder/`)을 사용해야 합니다. Athena에서, 다른 프로토콜(예: `s3a://amzn-s3-demo-bucket/folder/`)을 사용하는 위치는 포함 테이블에서 `MSCK REPAIR TABLE` 쿼리를 실행할 때 쿼리 실패를 초래하게 됩니다.
+ Amazon S3 경로가 camel 표기 대신 소문자인지 확인합니다(예: `userId` 대신 `userid`). S3 경로가 camel 표기인 경우 `MSCK REPAIR TABLE`은 AWS Glue Data Catalog에 파티션을 추가하지 않습니다. 자세한 내용은 [MSCK REPAIR TABLE](msck-repair-table.md) 섹션을 참조하세요.
+ `MSCK REPAIR TABLE`은 일치하는 파티션 스키마를 찾기 위해 폴더와 하위 폴더를 모두 스캔하기 때문에 별도의 폴더 계층 구조에 있는 별도의 테이블에 데이터를 보관해야 합니다. 예를 들어 테이블 1의 데이터를 `s3://amzn-s3-demo-bucket1`에 두고 테이블 2에 대한 데이터을 `s3://amzn-s3-demo-bucket1/table-2-data`에 두었다고 가정합시다. 두 테이블이 모두 문자열로 분할된 경우 `MSCK REPAIR TABLE`은 테이블 2의 파티션을 테이블 1에 추가합니다. 이를 방지하려면 대신에 `s3://amzn-s3-demo-bucket1` 및 `s3://amzn-s3-demo-bucket2`와 같은 별도의 폴더 구조를 사용하세요. 이 동작은 Amazon EMR과 Apache Hive에서도 동일합니다.
+ Athena와 함께 AWS Glue Data Catalog를 사용하는 경우 계정 및 테이블당 파티션의 서비스 할당량은 [AWS Glue 엔드포인트 및 할당량](https://docs.aws.amazon.com/general/latest/gr/glue.html)을 참조하세요.
  + Athena는 1천만 개의 파티션이 있는 AWS Glue 테이블에 대한 쿼리를 지원하지만, 단일 스캔으로 1백만 개 이상의 파티션을 읽을 수는 없습니다. 이러한 시나리오에서는 파티션 인덱싱이 유용할 수 있습니다. 자세한 내용을 알아보려면 AWS Big Data Blog(빅 데이터 블로그) 문서인 [Improve Amazon Athena query performance using AWS Glue Data Catalog partition indexes](https://aws.amazon.com/blogs/big-data/improve-amazon-athena-query-performance-using-aws-glue-data-catalog-partition-indexes/)(파티션 인덱스를 사용하여 Amazon Athena 쿼리 성능 향상)를 참조하세요.
+ AWS Glue Data Catalog를 사용하는 경우 파티션 할당량 증가를 요청하려면 [AWS Glue의 Service Quotas 콘솔](https://console.aws.amazon.com/servicequotas/home?region=us-east-1#!/services/glue/quotas)을 방문하세요.

## 분할된 데이터로 테이블 생성 및 로드
<a name="partitions-creating-loading"></a>

파티션을 사용하는 테이블을 생성하려면 [CREATE TABLE](create-table.md) 문에 `PARTITIONED BY` 절을 사용합니다. `PARTITIONED BY` 절은 다음 예와 같이 데이터를 분할하는 키를 정의합니다. `LOCATION` 절은 분할된 데이터의 루트 위치를 지정합니다.

```
CREATE EXTERNAL TABLE users (
first string,
last string,
username string
)
PARTITIONED BY (id string)
STORED AS parquet
LOCATION 's3://amzn-s3-demo-bucket'
```

테이블을 생성한 후 쿼리를 위해 파티션에 데이터를 로드합니다. Hive 스타일 파티션의 경우, [MSCK REPAIR TABLE](msck-repair-table.md)을(를) 실행합니다. Hive 스타일이 아닌 파티션의 경우, [ALTER TABLE ADD PARTITION](alter-table-add-partition.md)을(를) 사용하여 파티션을 수동으로 추가합니다.

## 쿼리를 위해 Hive 스타일 및 비 Hive 스타일 데이터 준비
<a name="partitions-preparing-data"></a>

다음 섹션에서는 Athena에서 쿼리하기 위해 Hive 스타일 및 비 Hive 스타일 데이터를 준비하는 방법을 보여줍니다.

### 시나리오 1: Hive 형식으로 Amazon S3에 저장된 데이터
<a name="scenario-1-data-already-partitioned-and-stored-on-s3-in-hive-format"></a>

이 시나리오에서는 Amazon S3에 있는 별도의 폴더에 파티션이 저장됩니다. 예를 들어 다음은 지정된 접두사 아래에 S3 객체를 나열하는 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/ls.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/ls.html) 명령으로 출력된 샘플 광고 노출에 대한 부분 목록입니다.

```
aws s3 ls s3://elasticmapreduce/samples/hive-ads/tables/impressions/

    PRE dt=2009-04-12-13-00/
    PRE dt=2009-04-12-13-05/
    PRE dt=2009-04-12-13-10/
    PRE dt=2009-04-12-13-15/
    PRE dt=2009-04-12-13-20/
    PRE dt=2009-04-12-14-00/
    PRE dt=2009-04-12-14-05/
    PRE dt=2009-04-12-14-10/
    PRE dt=2009-04-12-14-15/
    PRE dt=2009-04-12-14-20/
    PRE dt=2009-04-12-15-00/
    PRE dt=2009-04-12-15-05/
```

여기서 로그는 날짜, 시간 및 분 단위로 설정된 열 이름(dt)으로 저장됩니다. 분할된 열의 상위 폴더 위치, 스키마 및 이름을 DDL에 포함하면 Athena가 해당 하위 폴더의 데이터를 쿼리할 수 있습니다.

#### 테이블 생성
<a name="creating-a-table"></a>

이 데이터로 테이블을 생성하려면 다음 Athena DDL 문과 같이 'dt'를 따라 파티션을 생성합니다.

```
CREATE EXTERNAL TABLE impressions (
    requestBeginTime string,
    adId string,
    impressionId string,
    referrer string,
    userAgent string,
    userCookie string,
    ip string,
    number string,
    processId string,
    browserCookie string,
    requestEndTime string,
    timers struct<modelLookup:string, requestTime:string>,
    threadId string,
    hostname string,
    sessionId string)
PARTITIONED BY (dt string)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://elasticmapreduce/samples/hive-ads/tables/impressions/' ;
```

이 테이블은 Hive의 기본 JSON serializer-deserializer를 사용하여 Amazon S3에 저장된 JSON 데이터를 읽습니다. 지원되는 형식에 대한 자세한 내용은 [데이터에 적합한 SerDe 선택](supported-serdes.md) 단원을 참조하세요.

#### MSCK REPAIR TABLE 실행
<a name="run-msck-repair-table"></a>

`CREATE TABLE` 쿼리 실행 후 Athena 쿼리 편집기에서 `MSCK REPAIR TABLE` 명령을 실행하여 다음 예와 같이 파티션을 로드합니다.

```
MSCK REPAIR TABLE impressions
```

이 명령을 실행하면 데이터를 쿼리할 준비가 됩니다.

#### 데이터 쿼리
<a name="query-the-data"></a>

파티션 열을 사용하여 노출 테이블의 데이터를 쿼리합니다. 다음은 그 예입니다.

```
SELECT dt,impressionid FROM impressions WHERE dt<'2009-04-12-14-00' and dt>='2009-04-12-13-00' ORDER BY dt DESC LIMIT 100
```

이 쿼리는 다음과 비슷한 결과를 표시합니다.

```
2009-04-12-13-20    ap3HcVKAWfXtgIPu6WpuUfAfL0DQEc
2009-04-12-13-20    17uchtodoS9kdeQP1x0XThKl5IuRsV
2009-04-12-13-20    JOUf1SCtRwviGw8sVcghqE5h0nkgtp
2009-04-12-13-20    NQ2XP0J0dvVbCXJ0pb4XvqJ5A4QxxH
2009-04-12-13-20    fFAItiBMsgqro9kRdIwbeX60SROaxr
2009-04-12-13-20    V4og4R9W6G3QjHHwF7gI1cSqig5D1G
2009-04-12-13-20    hPEPtBwk45msmwWTxPVVo1kVu4v11b
2009-04-12-13-20    v0SkfxegheD90gp31UCr6FplnKpx6i
2009-04-12-13-20    1iD9odVgOIi4QWkwHMcOhmwTkWDKfj
2009-04-12-13-20    b31tJiIA25CK8eDHQrHnbcknfSndUk
```

### 시나리오 2: 데이터가 Hive 형식으로 분할되지 않음
<a name="scenario-2-data-is-not-partitioned"></a>

다음 예에서 `aws s3 ls` 명령은 Amazon S3에 저장된 [ELB](elasticloadbalancer-classic-logs.md) 로그를 보여줍니다. 데이터 레이아웃이 `key=value` 페어를 사용하지 않으므로 Hive 형식이 아니라는 점에 유의하세요. (`aws s3 ls` 명령에 대한 `--recursive` 옵션은 지정된 디렉터리 또는 접두사 아래의 모든 파일 또는 객체를 나열하도록 지정합니다.)

```
aws s3 ls s3://athena-examples-myregion/elb/plaintext/ --recursive

2016-11-23 17:54:46   11789573 elb/plaintext/2015/01/01/part-r-00000-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:46    8776899 elb/plaintext/2015/01/01/part-r-00001-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:46    9309800 elb/plaintext/2015/01/01/part-r-00002-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47    9412570 elb/plaintext/2015/01/01/part-r-00003-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47   10725938 elb/plaintext/2015/01/01/part-r-00004-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:46    9439710 elb/plaintext/2015/01/01/part-r-00005-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47          0 elb/plaintext/2015/01/01_$folder$
2016-11-23 17:54:47    9012723 elb/plaintext/2015/01/02/part-r-00006-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47    7571816 elb/plaintext/2015/01/02/part-r-00007-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:47    9673393 elb/plaintext/2015/01/02/part-r-00008-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48   11979218 elb/plaintext/2015/01/02/part-r-00009-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48    9546833 elb/plaintext/2015/01/02/part-r-00010-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48   10960865 elb/plaintext/2015/01/02/part-r-00011-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48          0 elb/plaintext/2015/01/02_$folder$
2016-11-23 17:54:48   11360522 elb/plaintext/2015/01/03/part-r-00012-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48   11211291 elb/plaintext/2015/01/03/part-r-00013-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:48    8633768 elb/plaintext/2015/01/03/part-r-00014-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:49   11891626 elb/plaintext/2015/01/03/part-r-00015-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:49    9173813 elb/plaintext/2015/01/03/part-r-00016-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:49   11899582 elb/plaintext/2015/01/03/part-r-00017-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:49          0 elb/plaintext/2015/01/03_$folder$
2016-11-23 17:54:50    8612843 elb/plaintext/2015/01/04/part-r-00018-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:50   10731284 elb/plaintext/2015/01/04/part-r-00019-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:50    9984735 elb/plaintext/2015/01/04/part-r-00020-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:50    9290089 elb/plaintext/2015/01/04/part-r-00021-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:50    7896339 elb/plaintext/2015/01/04/part-r-00022-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51    8321364 elb/plaintext/2015/01/04/part-r-00023-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51          0 elb/plaintext/2015/01/04_$folder$
2016-11-23 17:54:51    7641062 elb/plaintext/2015/01/05/part-r-00024-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51   10253377 elb/plaintext/2015/01/05/part-r-00025-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51    8502765 elb/plaintext/2015/01/05/part-r-00026-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51   11518464 elb/plaintext/2015/01/05/part-r-00027-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51    7945189 elb/plaintext/2015/01/05/part-r-00028-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51    7864475 elb/plaintext/2015/01/05/part-r-00029-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51          0 elb/plaintext/2015/01/05_$folder$
2016-11-23 17:54:51   11342140 elb/plaintext/2015/01/06/part-r-00030-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:51    8063755 elb/plaintext/2015/01/06/part-r-00031-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52    9387508 elb/plaintext/2015/01/06/part-r-00032-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52    9732343 elb/plaintext/2015/01/06/part-r-00033-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52   11510326 elb/plaintext/2015/01/06/part-r-00034-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52    9148117 elb/plaintext/2015/01/06/part-r-00035-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52          0 elb/plaintext/2015/01/06_$folder$
2016-11-23 17:54:52    8402024 elb/plaintext/2015/01/07/part-r-00036-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52    8282860 elb/plaintext/2015/01/07/part-r-00037-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:52   11575283 elb/plaintext/2015/01/07/part-r-00038-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:53    8149059 elb/plaintext/2015/01/07/part-r-00039-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:53   10037269 elb/plaintext/2015/01/07/part-r-00040-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:53   10019678 elb/plaintext/2015/01/07/part-r-00041-ce65fca5-d6c6-40e6-b1f9-190cc4f93814.txt
2016-11-23 17:54:53          0 elb/plaintext/2015/01/07_$folder$
2016-11-23 17:54:53          0 elb/plaintext/2015/01_$folder$
2016-11-23 17:54:53          0 elb/plaintext/2015_$folder$
```

#### ALTER TABLE ADD PARTITION 실행
<a name="run-alter-table-add-partition"></a>

데이터가 Hive 형식이 아니므로 `MSCK REPAIR TABLE` 명령을 사용하여 테이블을 생성한 후 테이블에 파티션을 추가합니다. 그 대신 [ALTER TABLE ADD PARTITION](alter-table-add-partition.md) 명령을 사용하여 각 파티션을 수동으로 추가할 수 있습니다. 예를 들어 s3://athena-examples-*myregion*/elb/plaintext/2015/01/01/에 데이터를 로드하려면 다음 쿼리를 실행합니다. 각 Amazon S3 폴더에 대해 별도의 파티션 열이 필요하지 않으며, 파티션 키 값이 Amazon S3 키와 다를 수 있습니다.

```
ALTER TABLE elb_logs_raw_native_part ADD PARTITION (dt='2015-01-01') location 's3://athena-examples-us-west-1/elb/plaintext/2015/01/01/'
```

파티션이 이미 있는 경우 오류(파티션이 이미 있습니다.)가 수신됩니다. 이 오류를 방지하기 위해 `IF NOT EXISTS` 절을 사용할 수 있습니다. 자세한 내용은 [ALTER TABLE ADD PARTITION](alter-table-add-partition.md) 섹션을 참조하세요. 파티션을 제거하려면 [ALTER TABLE DROP PARTITION](alter-table-drop-partition.md)을 사용합니다.

## 파티션 프로젝션 고려
<a name="partitions-partition-projection"></a>

파티션을 직접 관리하지 않으려면 파티션 프로젝션을 사용합니다. 파티션 프로젝션은 구조가 미리 알려진 고도로 분할된 테이블에 대한 옵션입니다. 파티션 프로젝션에서 파티션 값 및 위치는 메타데이터 리포지토리에서 읽지 않고 구성하는 테이블 속성에서 계산됩니다. 인메모리 계산은 원격 조회보다 빠르기 때문에 파티션 프로젝션을 사용하면 쿼리 런타임을 크게 줄일 수 있습니다.

자세한 내용은 [Amazon Athena에서 파티션 프로젝션 사용](partition-projection.md) 섹션을 참조하세요.

## 추가 리소스
<a name="partitions-additional-resources"></a>
+ Firehose 데이터의 분할 옵션에 대한 자세한 내용은 [Amazon Data Firehose 예제](partition-projection-kinesis-firehose-example.md) 섹션을 참조하세요.
+ [JDBC 드라이버](connect-with-jdbc.md)를 사용하여 파티션 추가를 자동화할 수도 있습니다.
+ CTAS 및 INSERT INTO를 사용하여 데이터 세트를 분할할 수 있습니다. 자세한 내용은 [ETL 및 데이터 분석에 CTAS 및 INSERT INTO 사용](ctas-insert-into-etl.md) 섹션을 참조하세요.