

 Amazon Redshift는 패치 198부터 새 Python UDF 생성을 더 이상 지원하지 않습니다. 기존 Python UDF는 2026년 6월 30일까지 계속 작동합니다. 자세한 내용은 [블로그 게시물](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)을 참조하세요.

# Amazon Redshift에서 데이터 로드
<a name="t_Loading_data"></a>

Amazon Redshift 데이터베이스에 데이터를 로드하는 방법에는 여러 가지가 있습니다. 로드하는 데 널리 사용되는 데이터 소스 중 하나는 Amazon S3 파일입니다. 다음 표에는 Amazon S3 소스로 시작하는 데 사용할 수 있는 몇 가지 방법이 요약되어 있습니다.


| 사용 방법 | 설명 | 필요한 경우 | 
| --- | --- | --- | 
| COPY 명령 | 배치 파일 모으기를 실행하여 Amazon S3 파일에서 데이터를 로드합니다. 이 방법은 Amazon Redshift의 병렬 처리 기능을 활용합니다. 자세한 내용은 [COPY 명령으로 테이블 로드](t_Loading_tables_with_the_COPY_command.md) 섹션을 참조하세요. | 배치 파일 모으기를 수동으로 시작하기 위한 기본 데이터 로드 요구 사항이 필요할 때 사용해야 합니다. 이 방법은 주로 사용자 지정 및 서드 파티 파일 모으기 파이프라인이나 일회성 또는 임시 파일 모으기 워크로드에 사용됩니다. | 
| COPY... CREATE JOB 명령(자동 복사) | 추적된 Amazon S3 경로에 새 파일이 생성되면 COPY 명령을 자동으로 실행합니다. 자세한 내용은 [Amazon S3 버킷에서 자동으로 파일을 복사하기 위해 S3 이벤트 통합 만들기](loading-data-copy-job.md) 섹션을 참조하세요. | Amazon S3에 새 파일이 생성될 때 파일 모으기 파이프라인이 데이터를 자동으로 모아야 하는 경우 사용해야 합니다. Amazon Redshift는 데이터 중복을 방지하기 위해 모은 파일을 추적합니다. 이 방법을 사용하려면 Amazon S3 버킷 소유자의 구성이 필요합니다. | 
| 데이터 레이크 쿼리에서 로드 | Amazon S3 파일에서 데이터 레이크 쿼리를 실행할 외부 테이블을 생성한 다음 INSERT INTO 명령을 실행하여 데이터 레이크 쿼리의 결과를 로컬 테이블에 로드합니다. 자세한 내용은 [Redshift Spectrum용 외부 테이블](c-spectrum-external-tables.md) 섹션을 참조하세요. | 다음 시나리오 중 하나에서 사용해야 합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/t_Loading_data.html) | 
| 고려할 수 있는 기타 방법 | 
| 스트리밍 수집  | 스트리밍 모으기를 사용하면 지연 시간이 짧고 빠른 속도로 Amazon Kinesis Data Streams 및 Amazon Managed Streaming for Apache Kafka에서 Amazon Redshift 프로비저닝된 또는 Redshift Serverless 구체화된 뷰로 스트림 데이터를 모을 수 있습니다. 자세한 내용은 [Amazon Kinesis Data Streams Streams에서 수집 시작](materialized-view-streaming-ingestion-getting-started.md) 및 [Apache Kafka 소스에서 스트리밍 수집 시작하기](materialized-view-streaming-ingestion-getting-started-MSK.md) 섹션을 참조하세요. | 데이터를 Amazon S3의 파일로 먼저 스트리밍한 다음 Amazon S3에서 로드하는 사용 사례에서 고려해야 합니다. Amazon S3에 데이터를 보관할 필요가 없는 경우 Amazon Redshift로 데이터를 직접 스트리밍하는 것이 좋을 수 있습니다. | 
| 데이터 레이크 쿼리 실행 | 테이블의 콘텐츠를 로컬 테이블에 모으는 대신 데이터 레이크 테이블에서 직접 쿼리를 실행합니다. 자세한 내용은 [Amazon Redshift Spectrum](c-using-spectrum.md) 섹션을 참조하세요. | 사용 사례에서 Amazon Redshift의 로컬 테이블 쿼리 성능이 필요하지 않은 경우 사용해야 합니다. | 
| Amazon Redshift 쿼리 에디터 v2를 사용하여 배치 로드 | Amazon Redshift 쿼리 에디터 v2에서 배치 파일 모으기 워크로드를 시각적으로 준비하고 실행할 수 있습니다. 자세한 내용은 **Amazon Redshift 관리 가이드의 [S3에서 데이터 로드](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-loading.html#query-editor-v2-loading-data)를 참조하세요. | 쿼리 에디터 v2에서 COPY 문을 준비하고 시각적 도구를 통해 COPY 문 준비 프로세스를 간소화하려는 경우 사용해야 합니다. | 
| Amazon Redshift 쿼리 에디터 v2를 사용하여 로컬 파일에서 데이터 로드 | Amazon S3에 파일을 수동으로 업로드할 필요 없이 데스크톱에서 Amazon Redshift 테이블로 직접 파일을 업로드할 수 있습니다. 자세한 내용은 **Amazon Redshift 관리 가이드의 [로컬 파일 설정 및 워크플로우에서 데이터 로드](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-loading.html#query-editor-v2-loading-data-local)를 참조하세요. | 일회성 쿼리 목적으로 로컬 컴퓨터에서 빠르게 파일을 로드해야 할 경우 사용해야 합니다. 이 방법을 사용하면 Amazon Redshift 쿼리 에디터 v2가 고객 소유의 Amazon S3 버킷에 파일을 임시로 저장하고 이 Amazon S3 경로를 사용하여 복사 명령을 실행합니다. | 

COPY 명령은 테이블을 로드하는 가장 효율적인 방법입니다. INSERT 명령을 사용하여 데이터를 테이블에 추가할 수도 있지만 COPY를 사용하는 것보다 효율은 훨씬 떨어집니다. COPY 명령은 여러 데이터 파일 또는 여러 데이터 스트림에서 동시에 읽을 수 있습니다. Amazon Redshift는 Amazon Redshift 노드에 워크로드를 할당하고 노드 슬라이스 전체에 데이터 배포 및 행 정렬을 포함한 로드 작업을 병렬로 수행합니다.

**참고**  
Amazon Redshift Spectrum 외부 테이블은 읽기 전용입니다. 외부 테이블로 복사 또는 삽입할 수 없습니다.

다른 AWS 리소스에 있는 데이터에 액세스하려면 이러한 리소스에 액세스하고 데이터 액세스에 필요한 작업을 수행할 권한이 Amazon Redshift에 있어야 합니다. AWS Identity and Access Management(IAM)를 사용하면 Amazon Redshift 리소스와 데이터에 대한 사용자의 액세스를 제한할 수 있습니다.

초기 데이터 로드 후 상당한 양의 데이터를 추가, 수정 또는 삭제하는 경우, VACUUM 명령을 실행해 데이터를 재구성하고 삭제 후 스페이스를 회수하는 후속 작업을 수행해야 합니다. 또한 ANALYZE 명령을 실행하여 테이블 통계를 업데이트해야 합니다.

**Topics**
+ [COPY 명령으로 테이블 로드](t_Loading_tables_with_the_COPY_command.md)
+ [Amazon S3 버킷에서 자동으로 파일을 복사하기 위해 S3 이벤트 통합 만들기](loading-data-copy-job.md)
+ [DML 명령을 사용하여 테이블 로드](t_Updating_tables_with_DML_commands.md)
+ [전체 복사 수행](performing-a-deep-copy.md)
+ [테이블 분석](t_Analyzing_tables.md)
+ [테이블 Vacuum](t_Reclaiming_storage_space202.md)
+ [동시 쓰기 작업 관리](c_Concurrent_writes.md)
+ [튜토리얼: Amazon S3에서 데이터 로드](tutorial-loading-data.md)

# COPY 명령으로 테이블 로드
<a name="t_Loading_tables_with_the_COPY_command"></a>

COPY 명령은 Amazon Redshift 대량 병렬 처리(MPP) 아키텍처를 활용하여 Amazon S3의 파일, DynamoDB 테이블 또는 하나 이상의 원격 호스트의 텍스트 출력에서 병렬로 데이터를 읽고 로드합니다.

COPY 명령의 모든 옵션을 익히기 전에 Amazon S3 데이터를 로드하는 기본 옵션을 익히는 것이 좋습니다. **Amazon Redshift 시작 가이드에서는 COPY 명령을 통해 기본 IAM 역할을 사용하여 Amazon S3 데이터를 로드하는 간단한 방법을 보여줍니다. 자세한 내용은 [4단계: Amazon S3에서 Amazon Redshift로 데이터 로드](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-create-sample-db.html)를 참조하세요.

**참고**  
대량의 데이터를 로드하려면 COPY 명령을 사용하는 것이 가장 좋습니다. 테이블을 채우는 데 개별적인 INSERT문을 사용하는 방식은 엄청나게 느릴 수 있습니다. 데이터가 다른 Amazon Redshift 데이터베이스 테이블에 이미 있는 경우에는, INSERT INTO ... SELECT 또는 CREATE TABLE AS를 사용하여 성능을 개선할 수 있습니다. 자세한 내용은 [INSERT](r_INSERT_30.md) 또는 [CREATE TABLE AS](r_CREATE_TABLE_AS.md) 섹션을 참조하세요.

다른 AWS 리소스에서 데이터를 로드하려면 리소스에 액세스하고 필요한 작업을 수행할 권한이 Amazon Redshift에 있어야 합니다.

COPY 명령을 사용하여 테이블로 데이터를 로드하는 권한을 부여하거나 취소하려면 INSERT 권한을 부여하거나 취소합니다.

데이터를 Amazon Redshift 테이블로 로드하려면 올바른 형식이어야 합니다. 이 섹션에서는 로드 전에 데이터를 준비 및 확인하고 실행 전에 COPY 문을 확인하는 방법을 살펴봅니다.

파일의 정보를 보호하기 위해 Amazon S3 버킷으로 업로드하기 전에 데이터 파일을 암호화할 수 있습니다. COPY는 로드를 수행하면서 데이터를 복호화합니다. 사용자에게 임시 보안 자격 증명을 제공하여 로드 데이터에 대한 액세스를 제한할 수도 있습니다. 임시 보안 자격 증명은 유효 기간이 짧고 만료 후 재사용이 불가능하기 때문에 보안을 강화하는 효과가 있습니다.

Amazon Redshift는 압축되지 않고 구분된 데이터를 빠르게 로드할 수 있도록 COPY에 특성이 내장되어 있습니다. 그러나 파일 업로드 시간을 절약하기 위해 gzip, lzop 또는 bzip2를 사용하여 파일을 압축할 수 있습니다.

COPY 쿼리에 ESCAPE, REMOVEQUOTES 및 FIXEDWIDTH와 같은 키워드가 있으면 압축되지 않은 데이터의 자동 분할이 지원되지 않습니다. 하지만 CSV 키워드는 지원됩니다.

AWS 클라우드 내에서 전송 중인 데이터 보안을 위해 Amazon Redshift는 COPY, UNLOAD, 백업 및 복원 작업을 수행할 때 하드웨어 가속화 SSL을 사용하여 Amazon S3 또는 Amazon DynamoDB와 통신합니다.

Amazon DynamoDB 테이블에서 직접 테이블을 로드하는 경우 사용하는 Amazon DynamoDB 프로비저닝 처리량의 양을 제어하는 옵션이 있습니다.

또는 COPY 명령이 입력 데이터를 분석하여 로드 프로세스의 일환으로 최적의 압축 인코딩을 테이블에 자동으로 적용하도록 할 수도 있습니다.

**Topics**
+ [자격 증명 및 액세스 권한](loading-data-access-permissions.md)
+ [입력 데이터 준비](t_preparing-input-data.md)
+ [Amazon S3에서 데이터 로드](t_Loading-data-from-S3.md)
+ [Amazon EMR에서 데이터 로드](loading-data-from-emr.md)
+ [원격 호스트에서 데이터 로드](loading-data-from-remote-hosts.md)
+ [Amazon DynamoDB 테이블에서 데이터 로드](t_Loading-data-from-dynamodb.md)
+ [데이터가 올바로 로드되었는지 확인](verifying-that-data-loaded-correctly.md)
+ [입력 데이터 확인](t_Validating_input_files.md)
+ [자동 압축을 사용하여 테이블 로드](c_Loading_tables_auto_compress.md)
+ [좁은 테이블의 스토리지 최적화](c_load_compression_hidden_cols.md)
+ [열 기본값 로드](c_loading_default_values.md)
+ [데이터 로드 문제 해결](t_Troubleshooting_load_errors.md)

# 자격 증명 및 액세스 권한
<a name="loading-data-access-permissions"></a>

 Amazon S3, Amazon DynamoDB, Amazon EMR, Amazon EC2 등의 다른 AWS 리소스를 사용하여 데이터를 로드 또는 언로드하려면 리소스에 액세스하고 데이터 액세스에 필요한 작업을 수행할 권한이 Amazon Redshift에 있어야 합니다. 예를 들어 Amazon S3에서 데이터를 로드하려면 COPY에 버킷에 대한 LIST 액세스 권한과 버킷 객체에 대한 GET 액세스 권한이 있어야 합니다.

리소스에 액세스할 수 있는 권한을 얻으려면 Amazon Redshift가 인증되어야 합니다. 역할 기반 액세스 제어 또는 키 기반 액세스 제어를 선택할 수 있습니다. 이 섹션에서는 이 두 가지 방법의 개요를 살펴봅니다. 자세한 내용과 예는 [다른 AWS 리소스에 대한 액세스 권한](copy-usage_notes-access-permissions.md) 섹션을 참조하세요.

## 역할 기반 액세스 제어
<a name="loading-data-access-role-based"></a>

역할 기반 액세스 제어를 통해 Amazon Redshift는 AWS Identity and Access Management(IAM) 역할을 임시로 수임합니다. 그런 다음 역할에 부여되는 권한에 따라 Amazon Redshift가 필요한 AWS 리소스에 액세스할 수 있습니다.

역할 기반 액세스 제어는 AWS 자격 증명을 보호하는 것은 물론이고 AWS 리소스와 민감한 사용자 데이터에 대한 액세스를 더욱 안전하게, 그리고 세분화하여 제어할 수 있다는 점에서 더욱 바람직합니다.

역할 기반 액세스 제어를 사용하려면 먼저 Amazon Redshift 서비스 역할 유형을 사용하여 IAM 역할을 생성한 후 데이터 웨어하우스에 연결해야 합니다. 이 역할에는 최소한 [COPY, UNLOAD 및 CREATE LIBRARY 작업을 위한 IAM 권한](copy-usage_notes-access-permissions.md#copy-usage_notes-iam-permissions)에 나열된 권한이 있어야 합니다. IAM 역할을 생성하여 클러스터에 연결하는 단계는 *Amazon Redshift 관리 가이드*의 [Amazon Redshift 클러스터가 AWS 서비스에 액세스할 수 있도록 IAM 역할 생성](https://docs.aws.amazon.com/redshift/latest/mgmt/authorizing-redshift-service.html#authorizing-redshift-service-creating-an-iam-role) 섹션을 참조하세요.

Amazon Redshift 관리 콘솔, CLI 또는 API를 사용하여 역할을 클러스터에 추가하거나, 클러스터와 연결된 역할을 확인할 수 있습니다. 자세한 내용은 *Amazon Redshift 관리 가이드*의 [IAM 역할을 사용하여 COPY 및 UNLOAD 작업 권한 부여](https://docs.aws.amazon.com/redshift/latest/mgmt/copy-unload-iam-role.html) 섹션을 참조하세요.

IAM 역할을 생성하면 IAM이 생성된 역할의 Amazon 리소스 이름(ARN)을 반환합니다. IAM 역할을 사용하여 COPY 명령을 실행하려면 IAM\$1ROLE 파라미터 또는 CREDENTIALS 파라미터를 사용하여 역할 ARN을 제공합니다.

다음 COPY 명령 예는 역할 `MyRedshiftRole`과 함께 IAM\$1ROLE 파라미터를 인증에 사용합니다.

```
COPY customer FROM 's3://amzn-s3-demo-bucket/mydata' 
IAM_ROLE 'arn:aws:iam::12345678901:role/MyRedshiftRole';
```

AWS 사용자는 최소한 [COPY, UNLOAD 및 CREATE LIBRARY 작업을 위한 IAM 권한](copy-usage_notes-access-permissions.md#copy-usage_notes-iam-permissions)에 나열된 권한이 있어야 합니다.

## 키 기반 액세스 제어
<a name="loading-data-access-key-based"></a>

키 기반 액세스 제어의 경우 데이터가 포함된 AWS 리소스에 액세스할 권한이 부여된 사용자에게 액세스 키 ID와 비밀 액세스 키를 제공합니다. 

**참고**  
액세스 키 ID와 비밀 액세스 키를 일반 텍스트 형태로 입력하기보다는 IAM 역할을 인증에 사용하는 것을 강력 권장합니다. 키 기반 액세스 제어를 선택하는 경우에는 절대 AWS 계정(루트) 자격 증명을 사용하지 마세요. 항상 IAM 사용자를 먼저 생성한 후 해당 사용자의 액세스 키 ID와 비밀 액세스 키를 입력합니다. IAM 사용자를 생성하는 단계는 [AWS 계정의 IAM 사용자 생성](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html)을 참조하세요.

# 입력 데이터 준비
<a name="t_preparing-input-data"></a>

입력 데이터가 데이터를 수신할 테이블 열과 호환되지 않는 경우, COPY 명령이 실패합니다.

입력 데이터가 유효한지 확인하려면 다음 지침을 사용하세요.
+ 데이터에는 최대 4바이트 길이의 UTF-8 문자만 포함될 수 있습니다.
+ CHAR 및 VARCHAR 문자열이 해당 열의 길이보다 길지 않은지 확인합니다. VARCHAR 문자열은 문자가 아니라 바이트로 측정됩니다. 따라서 가령 각각 4바이트를 차지하는 중국어의 4자 문자열은 VARCHAR(16) 열이 필요합니다.
+ 멀티바이트 문자는 VARCHAR 열에만 사용할 수 있습니다. 멀티바이트 문자의 길이가 4바이트를 넘지 않는지 확인합니다.
+ CHAR 열의 데이터에 1바이트 문자만 포함되어 있는지 확인합니다.
+ 레코드에서 마지막 필드를 표시하기 위해 특수 문자나 구문을 포함시키지 마세요. 이 필드는 구분 기호일 수 있습니다.
+ 데이터에 NUL(UTF-8 0000)이라고도 하는 null 종결자 또는 이진 0(0x000)이 포함된 경우, COPY 명령에서 NULL AS 옵션을 사용하여 이들 문자를 NULLS로 CHAR 또는 VARCHAR 열에 로드할 수 있습니다. `null as '\0'` 또는 `null as '\000'`. NULL AS를 사용하지 않는 경우, null 종결자로 인해 COPY가 실패합니다.
+ 문자열에 구분 기호와 삽입된 줄 바꿈 같은 특수 문자가 포함된 경우, [COPY](r_COPY.md) 명령과 함께 ESCAPE 옵션을 사용합니다.
+ 작은따옴표와 큰따옴표의 짝이 모두 맞는지 확인합니다.
+ 부동 소수점 문자열이 12.123 같은 표준 부동 소수점 형식이거나 1.0E4 같은 지수 형식인지 확인합니다.
+ 모든 타임스탬프 및 날짜 문자열이 [DATEFORMAT 및 TIMEFORMAT 문자열예제](r_DATEFORMAT_and_TIMEFORMAT_strings.md)의 사양을 따르는지 확인합니다. 기본 타임스탬프 형식은 YYYY-MM-DD hh:mm:ss이고 기본 날짜 형식은 YYYY-MM-DD입니다.
+ 개별 데이터 형식의 경계와 제한에 대한 자세한 내용은 [데이터 타입](c_Supported_data_types.md) 섹션을 참조하세요. 멀티바이트 문자 오류에 대한 자세한 내용은 [멀티바이트 문자 로드 오류](multi-byte-character-load-errors.md) 섹션을 참조하세요.

# Amazon S3에서 데이터 로드
<a name="t_Loading-data-from-S3"></a>

COPY 명령은 Amazon Redshift 대량 병렬 처리(MPP) 아키텍처를 활용하여 Amazon S3 버킷에 있는 하나 이상의 파일에서 병렬로 데이터를 읽고 로드합니다. 파일이 압축된 경우 데이터를 여러 파일로 분할하여 병렬 처리를 최대한 활용할 수 있습니다. (이 규칙에는 예외가 있습니다. 자세한 내용은 [데이터 파일 로드](https://docs.aws.amazon.com/redshift/latest/dg/c_best-practices-use-multiple-files.html)에서 설명합니다.) 또한 테이블에서 분산 키를 설정하면 병렬 처리를 최대한 활용할 수 있습니다. 기본 키에 대한 자세한 내용은 [쿼리 최적화를 위한 데이터 배포](t_Distributing_data.md) 섹션을 참조하세요.

데이터는 행당 한 줄씩 대상 테이블로 로드됩니다. 데이터 파일의 필드는 순서대로 왼쪽에서 오른쪽으로 테이블 열에 일치됩니다. 데이터 파일의 필드는 고정 너비이거나 문자 구분일 수 있습니다. 기본 구분자는 파이프(\$1)입니다. 기본적으로 모든 테이블 열이 로드되지만 필요할 경우, 쉼표로 분리된 열 목록을 정의할 수 있습니다. COPY 명령에서 지정된 열 목록에 포함되지 않은 테이블 열은 기본값으로 로드됩니다. 자세한 내용은 [열 기본값 로드](c_loading_default_values.md) 섹션을 참조하세요.

**Topics**
+ [압축 및 비압축 파일에서 데이터 로드](t_splitting-data-files.md)
+ [COPY와 함께 사용할 파일을 Amazon S3에 업로드](t_uploading-data-to-S3.md)
+ [COPY 명령을 사용하여 Amazon S3에서 로드](t_loading-tables-from-s3.md)

# 압축 및 비압축 파일에서 데이터 로드
<a name="t_splitting-data-files"></a>

압축된 데이터를 로드할 때 각 테이블의 데이터를 여러 파일로 분할하는 것이 좋습니다. 압축되지 않은 구분된 데이터를 로드할 때 COPY 명령은 대규모 병렬 처리(MPP) 및 스캔 범위를 사용하여 Amazon S3 버킷의 대용량 파일에서 데이터를 로드합니다.

## 여러 압축 파일에서 데이터 로드
<a name="t_splitting-data-files-compressed"></a>

압축된 데이터가 있는 경우 각 테이블의 데이터를 여러 파일로 분할하는 것이 좋습니다. COPY 명령은 여러 파일에서 병렬로 데이터를 로드할 수 있습니다. 집합에 공통 접두사 또는 *접두사 키*를 지정하거나 매니페스트 파일에서 파일을 명시적으로 나열하여 여러 파일을 로드할 수 있습니다.

데이터를 파일로 분할할 때는 파일 수가 클러스터에 있는 조각 수의 배수가 되도록 하세요. 이렇게 하면 Amazon Redshift가 데이터를 슬라이스 간에 균일하게 나눌 수 있습니다. 노드당 조각 수는 클러스터의 노드 크기에 따라 달라집니다. 예를 들어 각각의 dc2.large 컴퓨팅 노드에는 2개의 조각이 있고 각각의 dc2.8xlarge 컴퓨팅 노드에는 16개의 조각이 있습니다. 각 노드 크기의 슬라이스 수에 대한 자세한 내용은 *Amazon Redshift 관리 가이드*의 [클러스터 및 노드 정보](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#rs-about-clusters-and-nodes) 섹션을 참조하세요.

각 노드는 병렬 쿼리 실행에 참여하여 조각에 대한 데이터 분산 작업을 최대한 균일하게 실행합니다. 2개의 dc2.large 노드가 포함된 클러스터가 있는 경우 데이터를 4개의 파일 또는 4의 배수로 분할할 수 있습니다. Amazon Redshift는 워크로드를 분리할 때 파일 크기를 고려하지 않습니다. 따라서 압축 후 파일 크기가 1MB\$11GB로 대략 같은지 확인해야 합니다.

로드 파일을 식별하기 위해 객체 접두사를 사용하려면 공통 접두사를 사용해 각 파일의 이름을 지정합니다. 예를 들어 `venue.txt` 파일은 다음과 같이 4개의 파일로 분할할 수 있습니다.

```
venue.txt.1
venue.txt.2
venue.txt.3
venue.txt.4
```

버킷의 폴더에 여러 파일을 넣고 폴더 이름을 접두사로 지정하면 COPY가 해당 폴더의 모든 파일을 로드합니다. 매니페스트 파일을 사용하여 로드될 파일을 명시적으로 나열하면 서로 다른 버킷이나 폴더에 있는 파일도 로드할 수 있습니다.

매니페스트 파일에 대한 자세한 내용은 [매니페스트를 사용하여 데이터 파일 지정](r_COPY_command_examples.md#copy-command-examples-manifest) 섹션을 참조하세요.

## 압축되지 않은 구분된 파일에서 데이터 로드
<a name="t_splitting-data-files-uncompressed"></a>

압축되지 않은 구분된 데이터를 로드할 때 COPY 명령은 Amazon Redshift의 대규모 병렬 처리(MPP) 아키텍처를 사용합니다. Amazon Redshift는 병렬로 작동하는 조각을 자동으로 사용하여 Amazon S3 버킷의 대용량 파일에서 데이터 범위를 로드합니다. 병렬 로드가 발생하려면 파일을 구분해야 합니다. 예를 들어 파이프로 구분됩니다. CSV 파일에는 COPY 명령을 사용한 자동 병렬 데이터 로드도 사용할 수 있습니다. 테이블에서 배포 키를 설정하여 병렬 처리를 활용할 수도 있습니다. 기본 키에 대한 자세한 내용은 [쿼리 최적화를 위한 데이터 배포](t_Distributing_data.md) 섹션을 참조하세요.

COPY 쿼리에 ESCAPE, REMOVEQUOTES 및 FIXEDWIDTH 키워드가 포함된 경우 자동 병렬 데이터 로드가 지원되지 않습니다.

하나 이상의 파일에서 대상 테이블로 데이터가 행당 한 줄씩 로드됩니다. 데이터 파일의 필드는 순서대로 왼쪽에서 오른쪽으로 테이블 열에 일치됩니다. 데이터 파일의 필드는 고정 너비이거나 문자 구분일 수 있습니다. 기본 구분자는 파이프(\$1)입니다. 기본적으로 모든 테이블 열이 로드되지만 필요할 경우, 쉼표로 분리된 열 목록을 정의할 수 있습니다. COPY 명령에서 지정된 열 목록에 포함되지 않은 테이블 열은 기본값으로 로드됩니다. 자세한 내용은 [열 기본값 로드](c_loading_default_values.md) 섹션을 참조하세요.

데이터가 압축되지 않고 분리된 경우 다음 일반 프로세스를 따라 Amazon S3에서 데이터를 로드합니다.

1. Amazon S3에 파일을 업로드합니다.

1. COPY 명령을 실행하여 테이블을 로드합니다.

1. 데이터가 올바로 로드되었는지 확인합니다.

COPY 명령의 예는 [COPY 예](r_COPY_command_examples.md) 섹션을 참조하세요. Amazon Redshift에 로드된 데이터에 대한 자세한 내용은 [STL\$1LOAD\$1COMMITS](r_STL_LOAD_COMMITS.md) 및 [STL\$1LOAD\$1ERRORS](r_STL_LOAD_ERRORS.md) 시스템 테이블을 확인하세요.

각각에 포함된 노드와 슬라이스에 대한 자세한 내용은 *Amazon Redshift 관리 가이드*의 [클러스터 및 노드 정보](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#rs-about-clusters-and-nodes) 섹션을 참조하세요.

# COPY와 함께 사용할 파일을 Amazon S3에 업로드
<a name="t_uploading-data-to-S3"></a>

Amazon S3에 텍스트 파일을 업로드할 때 취할 수 있는 몇 가지 접근 방식이 있습니다.
+ 압축 파일이 있는 경우 Amazon Redshift에서 병렬 처리를 최대한 활용하려면 대용량 파일을 분할하는 것이 좋습니다.
+ 반면에 COPY는 압축되지 않은 텍스트로 구분된 대용량 파일 데이터를 자동으로 분할하여 병렬 처리를 용이하게 하고 대용량 파일의 데이터를 효과적으로 배포합니다.

데이터 파일을 보관할 Amazon S3 버킷을 생성한 다음 이 버킷에 데이터 파일을 업로드합니다. 버킷 생성 및 파일 업로드에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [Amazon S3 버킷을 사용한 작업](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html)을 참조하세요.

**중요**  
데이터 파일을 보관하는 Amazon S3 버킷은 [REGION](copy-parameters-data-source-s3.md#copy-region) 옵션을 사용하여 Amazon S3 버킷이 위치한 리전을 지정하지 않는 한 클러스터와 동일한 AWS 리전에서 생성해야 합니다.

S3 IP 범위가 허용 목록에 추가되었는지 확인합니다. 필요한 S3 IP 범위에 대한 자세한 내용은 [네트워크 격리](https://docs.aws.amazon.com//redshift/latest/mgmt/security-network-isolation.html#network-isolation)를 참조하세요.

Amazon S3 콘솔을 사용하여 버킷을 생성할 때 리전을 선택하거나 Amazon S3 API 또는 CLI를 사용하여 버킷을 생성할 때 엔드포인트를 지정하여 특정 리전에서 Amazon S3 버킷을 생성할 수 있습니다.

데이터 로드 후 Amazon S3에 올바른 파일이 존재하는지 확인합니다.

**Topics**
+ [데이터 일관성 관리](managing-data-consistency.md)
+ [Amazon S3에 암호화된 데이터 업로드](t_uploading-encrypted-data.md)
+ [버킷에 올바른 파일이 존재하는지 확인](verifying-that-correct-files-are-present.md)

# 데이터 일관성 관리
<a name="managing-data-consistency"></a>

Amazon S3는 모든 AWS 리전의 Amazon S3 버킷에서 COPY, UNLOAD, INSERT(외부 테이블), CREATE EXTERNAL TABLE AS 및 Amazon Redshift Spectrum 작업에 강력한 쓰기 후 읽기 일관성을 제공합니다. 또한 Amazon S3 Select, Amazon S3 액세스 제어 목록, Amazon S3 객체 태그, 객체 메타데이터(예: HEAD 객체)에 대한 읽기 작업은 매우 일관적입니다. 데이터 일관성에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [Amazon S3 데이터 일관성 모델](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Introduction.html#ConsistencyModel)을 참조하세요.

# Amazon S3에 암호화된 데이터 업로드
<a name="t_uploading-encrypted-data"></a>

Amazon S3는 서버 측 암호화와 클라이언트 측 암호화를 모두 지원합니다. 이 항목에서는 서버 측 암호화와 클라이언트 측 암호화의 차이를 살펴보고, Amazon Redshift에서 클라이언트 측 암호화를 사용하는 단계를 설명합니다. 서버 측 암호화는 Amazon Redshift에 투명합니다.

## 서버 측 암호화
<a name="server-side-encryption"></a>

서버 측 암호화는 저장된 데이터 암호화입니다. 즉, Amazon S3는 데이터를 업로드할 때 데이터를 암호화하고 사용자가 데이터에 액세스할 때 데이터를 복호화합니다. COPY 명령을 사용하여 테이블을 로드하면 Amazon S3에서 서버 측 암호화된 객체나 암호화되지 않은 객체에서 로드하는 방식은 차이가 없습니다. 서버 측 암호화에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [서버 측 암호화 사용](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingServerSideEncryption.html)을 참조하세요.

## 클라이언트 측 암호화
<a name="client-side-encryption"></a>

클라이언트 측 암호화에서는 클라이언트 애플리케이션이 데이터 암호화, 암호화 키, 관련 도구를 관리합니다. 클라이언트 측 암호화를 사용하여 Amazon S3 버킷에 데이터를 업로드한 다음 ENCRYPTED 옵션 및 프라이빗 암호화 키와 함께 COPY 명령을 사용하여 데이터를 로드하면 보안을 강화할 수 있습니다.

봉투 암호화를 사용하여 데이터를 암호화합니다. *봉투 암호화*의 경우, 애플리케이션만이 모든 암호화를 처리합니다. 클라이언트 측 마스터 키 및 암호화되지 않은 데이터는 절대 AWS로 전송되지 않기 때문에 암호화 키를 안전하게 관리하는 것이 중요합니다. 암호화 키를 분실하면 데이터 암호를 해제할 수 없으며 AWS에서 암호화 키를 복구할 수 없습니다. 봉투 암호화는 빠른 대칭 암호화의 성능을 결합하는 동시에 비대칭 키를 사용하는 키 관리가 제공하는 보다 높은 수준의 보안을 유지합니다. 일회용 대칭 키(봉투 대칭 키)가 Amazon S3 암호화 클라이언트에 의해 생성되어 데이터를 암호화한 다음 이 키가 루트 키에 의해 암호화되고 Amazon S3에 데이터와 함께 저장됩니다. 로드 중 Amazon Redshift가 데이터에 액세스하면 암호화된 대칭 키가 검색되어 실제 키를 사용해 복호화된 다음 데이터가 복호화됩니다.

Amazon Redshift에서 Amazon S3 클라이언트 측 암호화 데이터로 작업하려면 사용하는 추가 요구 사항과 함께 *Amazon Simple Storage Service 사용 설명서*의 [클라이언트측 암호화를 사용하여 데이터 보호](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingClientSideEncryption.html)에 약술된 단계를 따릅니다.
+ **대칭 암호화 -** AWS SDK for Java `AmazonS3EncryptionClient` 클래스는 대칭 키 암호화에 기반하는 앞서 설명한 봉투 암호화를 사용합니다. 클라이언트 측 암호화된 데이터를 업로드하려면 이 클래스를 사용하여 Amazon S3 클라이언트를 생성합니다.
+ **256비트 AES 루트 대칭 키 -** 루트 키는 봉투(envelope) 키를 암호화합니다. 루트 키를 `AmazonS3EncryptionClient` 클래스의 인스턴스에 전달합니다. 데이터를 Amazon Redshift에 복사할 때 필요하므로 이 키를 저장합니다.
+ **암호화된 봉투(envelope) 키를 저장하기 위한 객체 메타데이터 -** 기본적으로 Amazon S3는 봉투(envelope) 키를 `AmazonS3EncryptionClient` 클래스에 대한 객체 메타데이터로 저장합니다. 객체 메타데이터로 저장된 암호화된 엔벌로프 키는 해독 프로세스에서 사용됩니다.

**참고**  
처음으로 암호화 API를 사용할 때 암호 암호화 오류 메시지가 표시되는 경우 사용 중인 버전의 JDK에 암호화 및 암호 해독 변환에 대한 최대 키 길이를 128비트로 제한하는 Java Cryptography Extension(JCE) Jurisdiction Policy File이 있을 수 있습니다. 이 문제를 해결하는 방법에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [AWS Java용 SDK를 사용하여 클라이언트 측 암호화 지정](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingClientSideEncryptionUpload.html)을 참조하세요.

COPY 명령을 사용하여 클라이언트 측에서 암호화된 파일을 Amazon Redshift 테이블에 로드하는 방법은 [Amazon S3에서 암호화된 데이터 파일 로드](c_loading-encrypted-files.md) 섹션을 참조하세요.

## 예: 클라이언트 측에서 암호화된 데이터 업로드
<a name="client-side-encryption-example"></a>

AWS Java용 SDK를 사용하여 클라이언트 측 암호화 데이터를 업로드하는 방법의 예는 *Amazon Simple Storage Service 사용 설명서*의 [클라이언트 측 암호화를 사용하여 데이터 보호](https://docs.aws.amazon.com/AmazonS3/latest/userguide/encrypt-client-side-symmetric-master-key.html)를 참조하세요.

두 번째 옵션은 데이터를 Amazon Redshift에 업로드하기 위해 클라이언트 측 암호화 과정에서 선택해야 하는 설정을 보여줍니다. 구체적으로 이 예는 객체 메타데이터를 사용하여 암호화된 엔벌로프 키를 저장하고 256비트 AES 루트 대칭 키를 사용하는 방법을 보여줍니다.

이 예에서는 AWS Java용 SDK를 사용하여 256비트 AES 대칭 루트 키를 생성하고 이를 파일에 저장하는 예제 코드를 제공합니다. 그런 다음 먼저 클라이언트 측에서 샘플 데이터를 암호화하는 S3 암호화 클라이언트를 사용하여 Amazon S3에 객체를 업로드합니다. 이 예에서는 객체를 다운로드하고 데이터가 같은지도 확인합니다.

# 버킷에 올바른 파일이 존재하는지 확인
<a name="verifying-that-correct-files-are-present"></a>

파일을 Amazon S3 버킷에 업로드한 후에는 버킷의 콘텐츠를 나열하여 올바른 파일이 모두 존재하고 원치 않는 파일이 없는지 확인하는 것이 좋습니다. 예를 들어 버킷 `amzn-s3-demo-bucket`에 `venue.txt.back` 파일이 보관된 경우, 해당 파일은 아마도 다음 명령에 의해 의도치 않게 로드될 것입니다.

```
COPY venue FROM 's3://amzn-s3-demo-bucket/venue' … ;
```

구체적으로 어떤 파일이 로드되는지 제어하려면 매니페스트 파일을 사용하여 데이터 파일을 명시적으로 나열합니다. 매니페스트 파일 사용에 대한 자세한 내용은 COPY 명령의 [copy_from_s3_manifest_file](copy-parameters-data-source-s3.md#copy-manifest-file) 옵션과 COPY 예의 [매니페스트를 사용하여 데이터 파일 지정](r_COPY_command_examples.md#copy-command-examples-manifest)를 참조하세요.

버킷의 콘텐츠 나열에 대한 자세한 내용은 *Amazon S3 Developer Guide*의 [Listing Object Keys](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ListingKeysUsingAPIs.html) 섹션을 참조하세요.

# COPY 명령을 사용하여 Amazon S3에서 로드
<a name="t_loading-tables-from-s3"></a>

[COPY](r_COPY.md) 명령을 사용하여 Amazon S3의 데이터 파일에서 병렬로 테이블을 로드합니다. Amazon S3 객체 접두사를 사용하거나 매니페스트 파일을 사용하여 로드할 파일을 지정할 수 있습니다.

접두사를 사용하여 로드할 파일을 지정하는 구문은 다음과 같습니다.

```
COPY <table_name> FROM 's3://<bucket_name>/<object_prefix>'
authorization;
```

 매니페스트 파일은 로드할 데이터 파일을 나열하는 JSON 형식 파일입니다. 매니페스트 파일을 사용하여 로드할 파일을 지정하는 구문은 다음과 같습니다.

```
COPY <table_name> FROM 's3://<bucket_name>/<manifest_file>'
authorization
MANIFEST;
```

로드할 테이블이 데이터베이스에 이미 존재하고 있어야 합니다. 테이블 생성에 대한 자세한 내용은 SQL 참조의 [CREATE TABLE](r_CREATE_TABLE_NEW.md) 섹션을 참조하세요.

*authorization* 값은 Amazon Redshift가 Amazon S3 객체에 액세스하는 데 필요한 AWS 권한 부여를 제공합니다. 필요한 권한에 대한 자세한 내용은 [COPY, UNLOAD 및 CREATE LIBRARY 작업을 위한 IAM 권한](copy-usage_notes-access-permissions.md#copy-usage_notes-iam-permissions) 섹션을 참조하세요. 선호되는 인증 방법은 IAM\$1ROLE 파라미터를 지정하고 IAM 역할의 Amazon 리소스 이름(ARN)에 필요한 권한을 제공하는 것입니다. 자세한 정보는 [역할 기반 액세스 제어](copy-usage_notes-access-permissions.md#copy-usage_notes-access-role-based)을 참조하세요.

IAM\$1ROLE 파라미터를 사용하여 인증하려면 다음 구문을 참조하여 *<aws-account-id>* 및 *<role-name>*을 바꿉니다.

```
IAM_ROLE 'arn:aws:iam::<aws-account-id>:role/<role-name>'
```

다음 예는 IAM 역할을 사용한 인증을 보여 줍니다.

```
COPY customer 
FROM 's3://amzn-s3-demo-bucket/mydata' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole';
```

기타 옵션에 대한 자세한 내용은 [권한 부여 파라미터](copy-parameters-authorization.md) 섹션을 참조하세요.

실제로 테이블을 로드하지 않고 데이터를 확인하려면 [COPY](r_COPY.md) 명령과 함께 NOLOAD 옵션을 사용하세요.

다음 예는 `venue.txt`라는 이름의 파일에서 파이프로 구분된 데이터의 첫 몇 행을 보여 줍니다.

```
1|Toyota Park|Bridgeview|IL|0
2|Columbus Crew Stadium|Columbus|OH|0
3|RFK Stadium|Washington|DC|0
```

파일을 Amazon S3에 업로드하기 전에 COPY 명령이 병렬 처리를 사용해 로드할 수 있도록 파일을 여러 파일로 분할합니다. 이때 파일 수는 클러스터 조각 수의 승수가 되어야 합니다. 이때는 압축 후 파일 크기가 1MB\$11GB로 거의 같아질 수 있도록 로딩 데이터 파일을 분할합니다. 자세한 내용은 [압축 및 비압축 파일에서 데이터 로드](t_splitting-data-files.md) 섹션을 참조하세요.

예를 들어 `venue.txt` 파일은 다음과 같이 4개의 파일로 분할할 수 있습니다.

```
venue.txt.1
venue.txt.2
venue.txt.3
venue.txt.4
```

다음 COPY 명령은 Amazon S3 버킷 `amzn-s3-demo-bucket`에서 접두사 'venue'가 있는 데이터 파일에서 파이프로 구분된 데이터를 사용해 VENUE 테이블을 로드합니다.

**참고**  
다음 예의 Amazon S3 버킷 `amzn-s3-demo-bucket`은 존재하지 않습니다. 기존 Amazon S3 버킷의 실제 데이터를 사용하는 샘플 COPY 명령은 [샘플 데이터 로드](https://docs.aws.amazon.com/redshift/latest/gsg/cm-dev-t-load-sample-data.html) 섹션을 참조하세요.

```
COPY venue FROM 's3://amzn-s3-demo-bucket/venue'
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
DELIMITER '|';
```

키 접두사 'venue'가 있는 Amazon S3 객체가 존재하지 않는 경우 로드가 실패합니다.

**Topics**
+ [매니페스트를 사용하여 데이터 파일 지정](loading-data-files-using-manifest.md)
+ [Amazon S3에서 압축된 데이터 파일 로드](t_loading-gzip-compressed-data-files-from-S3.md)
+ [Amazon S3에서 고정 너비 데이터 로드](t_loading_fixed_width_data.md)
+ [Amazon S3에서 멀티바이트 데이터 로드](t_loading_unicode_data.md)
+ [Amazon S3에서 암호화된 데이터 파일 로드](c_loading-encrypted-files.md)

# 매니페스트를 사용하여 데이터 파일 지정
<a name="loading-data-files-using-manifest"></a>

매니페스트를 사용하여 COPY 명령이 데이터 로드에 필요한 파일만 모두 로드하도록 할 수 있습니다. 매니페스트를 이용하면 다른 버킷, 다른 리전이나 접두사가 다른 파일에서 파일을 불러올 수 있습니다. COPY 명령에 대해 객체 경로를 제공하는 대신 로드할 파일을 명시적으로 나열하는 JSON 형식 텍스트 파일의 이름을 제공합니다. 매니페스트의 URL은 접두사만이 아니라 파일의 버킷 이름과 전체 객체 경로를 지정해야 합니다.

매니페스트 파일에 대한 자세한 내용은 [매니페스트를 사용한 데이터 파일 지정](r_COPY_command_examples.md#copy-command-examples-manifest)을 참조하세요.

다음 예는 버킷이 서로 다르고 날짜 스탬프로 시작되는 파일 이름을 가진 파일을 로드하는 JSON을 보여 줍니다.

```
{
  "entries": [
    {"url":"s3://amzn-s3-demo-bucket1/2013-10-04-custdata", "mandatory":true},
    {"url":"s3://amzn-s3-demo-bucket1/2013-10-05-custdata", "mandatory":true},
    {"url":"s3://amzn-s3-demo-bucket2/2013-10-04-custdata", "mandatory":true},
    {"url":"s3://amzn-s3-demo-bucket2/2013-10-05-custdata", "mandatory":true}
  ]
}
```

선택 사항인 `mandatory` 플래그는 파일이 없을 때 의 오류 반환 여부를 결정합니다. `mandatory`의 기본값은 `false`입니다. 필수 설정에 상관없이 파일이 발견되지 않으면 COPY는 종료됩니다.

다음은 앞 예에서 사용한 `cust.manifest` 매니페스트를 이용해 명령을 실행하는 예입니다.

```
COPY customer
FROM 's3://amzn-s3-demo-bucket/cust.manifest' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
MANIFEST;
```

## UNLOAD에 의해 생성된 매니페스트 사용
<a name="loading-data-files-using-unload-manifest"></a>

MANIFEST 파라미터를 사용하여 [UNLOAD](r_UNLOAD.md) 작업에 의해 생성된 매니페스트에는 COPY 작업에 필요하지 않은 키가 포함될 수 있습니다. 예를 들어 다음 `UNLOAD`매니페스트는 Amazon Redshift Spectrum 외부 테이블에 필요하고, `ORC` 또는 `Parquet` 파일 형식의 데이터 파일을 로드하는 데 필요한 `meta` 키를 포함합니다. `meta` 키에는 파일의 실제 크기(바이트 단위)인 값과 함께 `content_length` 키가 포함되어 있습니다. COPY 작업에는 `url` 키와 선택 사항인 `mandatory` 키만 필요합니다.

```
{
  "entries": [
    {"url":"s3://amzn-s3-demo-bucket/unload/manifest_0000_part_00", "meta": { "content_length": 5956875 }},
    {"url":"s3://amzn-s3-demo-bucket/unload/unload/manifest_0001_part_00", "meta": { "content_length": 5997091 }}
 ]
}
```

매니페스트 파일에 대한 자세한 내용은 [매니페스트를 사용하여 데이터 파일 지정](r_COPY_command_examples.md#copy-command-examples-manifest) 섹션을 참조하세요.

# Amazon S3에서 압축된 데이터 파일 로드
<a name="t_loading-gzip-compressed-data-files-from-S3"></a>

gzip, lzop 또는 bzip2를 사용해 압축된 데이터 파일을 로드하려면 해당 옵션인 GZIP, LZOP 또는 BZIP2를 포함시킵니다.

예를 들어 다음 명령은 lzop을 사용하여 압축한 파일에서 로드합니다.

```
COPY customer FROM 's3://amzn-s3-demo-bucket/customer.lzo' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
DELIMITER '|' LZOP;
```

**참고**  
lzop 압축으로 데이터 파일을 압축하고 **--filter 옵션을 사용하는 경우 COPY 명령은 이를 지원하지 않습니다.

# Amazon S3에서 고정 너비 데이터 로드
<a name="t_loading_fixed_width_data"></a>

고정 너비 데이터 파일은 데이터의 각 열의 길이가 균일합니다. 고정 너비 데이터 파일에서 각 필드의 길이와 위치는 정확히 동일합니다. 고정 너비 데이터 파일의 문자 데이터(CHAR 및 VARCHAR)의 경우, 너비를 균일하게 유지하기 위해 자리 표시자로 선행 공백 또는 후행 공백을 포함시켜야 합니다. 정수의 경우, 자리 표시자로 선행 제로를 사용해야 합니다. 고정 너비 데이터 파일에는 열을 분리하는 구분 기호가 없습니다.

고정 너비 데이터 파일을 기존 테이블로 로드하려면 COPY 명령에서 FIXEDWIDTH 파라미터를 사용합니다. 데이터가 올바로 로드되려면 테이블 사양이 fixedwidth\$1spec의 값과 일치해야 합니다.

파일에서 테이블로 고정 너비 데이터를 로드하려면 다음 명령을 실행합니다.

```
COPY table_name FROM 's3://amzn-s3-demo-bucket/prefix' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole' 
FIXEDWIDTH 'fixedwidth_spec';
```

*fixedwidth\$1spec* 파라미터는 콜론으로 분리된 각 열의 식별자와 각 열 너비가 포함된 문자열입니다. **column:width** 쌍은 쉼표로 구분됩니다. 식별자는 숫자, 문자 또는 숫자와 문자의 조합 중 어떤 것이든 가능합니다. 식별자는 테이블 자체와 아무 관련이 없으므로 사양에는 테이블과 동일한 순서로 열이 포함되어야 합니다.

다음 2개의 예에 나오는 사양은 동일하며, 첫 번째 사양은 숫자 식별자를 사용하고 두 번째 사양은 문자열 식별자를 사용합니다.

```
'0:3,1:25,2:12,3:2,4:6'
```

```
'venueid:3,venuename:25,venuecity:12,venuestate:2,venueseats:6'
```

다음 예는 상기 사양을 사용하여 VENUE 테이블에 로드할 수 있는 고정 너비 샘플 데이터를 보여 줍니다.

```
1  Toyota Park               Bridgeview  IL0
2  Columbus Crew Stadium     Columbus    OH0
3  RFK Stadium               Washington  DC0
4  CommunityAmerica Ballpark Kansas City KS0
5  Gillette Stadium          Foxborough  MA68756
```

다음 COPY 명령은 이 데이터 세트를 VENUE 테이블로 로드합니다.

```
COPY venue
FROM 's3://amzn-s3-demo-bucket/data/venue_fw.txt' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole' 
FIXEDWIDTH 'venueid:3,venuename:25,venuecity:12,venuestate:2,venueseats:6';
```

# Amazon S3에서 멀티바이트 데이터 로드
<a name="t_loading_unicode_data"></a>

데이터에 중국어나 키릴 문자 같이 ASCII가 아닌 멀티바이트 문자가 포함되어 있는 경우에는 VARCHAR 열에 데이터를 로드해야 합니다. VARCHAR 데이터 형식은 4바이트 UTF-8 문자를 지원하지만 CHAR 데이터 형식에서는 1바이트 ASCII 문자만 허용되기 때문입니다. Amazon Redshift 테이블에 5바이트 이상의 문자는 로드할 수 없습니다. CHAR 및 VARCHAR에 대한 자세한 내용은 [데이터 타입](c_Supported_data_types.md) 섹션을 참조하세요.

입력 파일이 어떤 인코딩을 사용하는지 확인하려면 Linux * `file` * 명령을 사용합니다.

```
$ file ordersdata.txt
ordersdata.txt: ASCII English text
$ file uni_ordersdata.dat
uni_ordersdata.dat: UTF-8 Unicode text
```

# Amazon S3에서 암호화된 데이터 파일 로드
<a name="c_loading-encrypted-files"></a>

COPY 명령을 사용하면 서버 측 암호화나 클라이언트 측 암호화 또는 이 둘을 모두 사용하여 Amazon S3에 업로드된 데이터 파일을 로드할 수 있습니다.

COPY 명령이 지원하는 Amazon S3 암호화 유형은 다음과 같습니다.
+ Amazon S3 관리형 키를 사용한 서버 측 암호화(SSE-S3)
+ AWS KMS keys(SSE-KMS)를 사용한 서버 측 암호화 지정
+ 클라이언트 측 대칭 루트 키를 사용한 클라이언트 측 암호화

COPY 명령이 지원하지 않는 Amazon S3 암호화 유형은 다음과 같습니다.
+ 고객 제공 키를 사용한 서버 측 암호화(SSE-C)
+ AWS KMS key를 사용한 클라이언트 측 암호화
+ 고객 제공 비대칭 루트 키를 사용한 클라이언트 측 암호화

Amazon S3 암호화에 대한 자세한 내용은 Amazon Simple Storage Service 사용 설명서의 [서버 측 암호화를 사용하여 데이터 보호](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html) 및 [클라이언트 측 암호화를 사용하여 데이터 보호](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingClientSideEncryption.html)를 참조하세요.

[UNLOAD](r_UNLOAD.md) 명령은 SSE-S3를 사용하여 자동으로 파일을 암호화합니다. 고객 관리형 대칭 키와 함께 SSE-KMS 또는 클라이언트측 암호화를 사용하여 언로드할 수도 있습니다. 자세한 내용은 [암호화된 데이터 파일 언로드](t_unloading_encrypted_files.md) 섹션을 참조하세요.

COPY 명령은 SSE-S3 및 SSE-KMS를 사용하여 암호화된 파일을 자동으로 인식하고 로드합니다. ENCRYPTED 옵션을 지정하고 키 값을 제공하여 클라이언트 측 대칭 루트 키를 사용해 암호화된 파일을 로드할 수 있습니다. 자세한 내용은 [Amazon S3에 암호화된 데이터 업로드](t_uploading-encrypted-data.md) 섹션을 참조하세요.

클라이언트 측에서 암호화된 데이터 파일을 로드하려면 MASTER\$1SYMMETRIC\$1KEY 파라미터를 사용하여 루트 키 값을 제공하고 ENCRYPTED 옵션을 포함시킵니다.

```
COPY customer FROM 's3://amzn-s3-demo-bucket/encrypted/customer' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
MASTER_SYMMETRIC_KEY '<root_key>' 
ENCRYPTED
DELIMITER '|';
```

gzip, lzop 또는 bzip2 압축된 암호화된 데이터 파일을 로드하려면 루트 키 값 및 ENCRYPTED 옵션과 함께 GZIP, LZOP 또는 BZIP2를 포함시킵니다.

```
COPY customer FROM 's3://amzn-s3-demo-bucket/encrypted/customer' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
MASTER_SYMMETRIC_KEY '<root_key>'
ENCRYPTED 
DELIMITER '|' 
GZIP;
```

# Amazon EMR에서 데이터 로드
<a name="loading-data-from-emr"></a>

COPY 명령을 사용하면 클러스터의 Hadoop 분산 파일 시스템(HDFS)에 고정 너비 파일, 문자로 구분된 파일, CSV 파일 또는 JSON 형식 파일 형식으로 텍스트 파일을 쓰도록 구성된 Amazon EMR 클러스터에서 병렬로 데이터를 로드할 수 있습니다.

## Amazon EMR에서 데이터를 로드하기 위한 프로세스
<a name="load-from-emr-process"></a>

이 섹션에서는 Amazon EMR 클러스터에서 데이터를 로드하는 프로세스를 단계별로 살펴봅니다. 다음 섹션에서는 각 단계에서 해야 할 일을 자세히 설명합니다.
+ **[1단계: IAM 권한 구성](#load-from-emr-steps-configure-iam)**

  Amazon EMR 클러스터를 생성하고 Amazon Redshift COPY 명령을 실행하는 사용자에게는 필요한 권한이 있어야 합니다.
+ **[2단계: Amazon EMR 클러스터 생성](#load-from-emr-steps-create-cluster)**

  Hadoop 분산 파일 시스템(HDFS)으로 텍스트 파일을 출력하도록 클러스터를 구성합니다. Amazon EMR 클러스터 ID와 클러스터의 메인 퍼블릭 DNS(클러스터를 호스팅하는 Amazon EC2 인스턴스의 엔드포인트)가 필요합니다.
+ **[3단계: Amazon Redshift 클러스터 퍼블릭 키와 클러스터 노드 IP 주소 검색](#load-from-emr-steps-retrieve-key-and-ips)**

  퍼블릭 키를 사용하면 Amazon Redshift 클러스터 노드가 호스트와의 SSH 연결을 설정할 수 있습니다. 각 클러스터 노드의 IP 주소를 사용하여 이러한 IP 주소를 사용하는 Amazon Redshift 클러스터로부터의 액세스를 허용하도록 호스트 보안 그룹을 구성합니다.
+ **[4단계: 각각의 Amazon EC2 호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키 추가](#load-from-emr-steps-add-key-to-host)** 

  호스트가 Amazon Redshift 클러스터를 인식하고 SSH 연결을 수락하도록 호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키를 추가합니다.
+ **[5단계: Amazon Redshift 클러스터의 모든 IP 주소를 수락하도록 호스트 구성](#load-from-emr-steps-configure-security-groups)** 

  Amazon EMR 인스턴스의 보안 그룹을 수정하여 Amazon Redshift IP 주소를 수락하도록 입력 규칙을 추가합니다.
+ **[6단계: COPY 명령을 실행하여 데이터 로드](#load-from-emr-steps-run-copy)**

  Amazon Redshift 데이터베이스에서 COPY 명령을 실행하여 Amazon Redshift 테이블로 데이터를 로드합니다.

## 1단계: IAM 권한 구성
<a name="load-from-emr-steps-configure-iam"></a>

Amazon EMR 클러스터를 생성하고 Amazon Redshift COPY 명령을 실행하는 사용자에게는 필요한 권한이 있어야 합니다.

**IAM 권한을 구성하려면**

1. Amazon EMR 클러스터를 생성할 사용자에 대해 다음의 권한을 추가합니다.

   ```
   ec2:DescribeSecurityGroups
   ec2:RevokeSecurityGroupIngress
   ec2:AuthorizeSecurityGroupIngress
   redshift:DescribeClusters
   ```

1. COPY 명령을 실행할 IAM 역할 또는 사용자에 대해 다음의 권한을 추가합니다.

   ```
   elasticmapreduce:ListInstances
   ```

1. 다음 권한을 Amazon EMR 클러스터의 IAM 역할에 추가합니다.

   ```
   redshift:DescribeClusters
   ```

## 2단계: Amazon EMR 클러스터 생성
<a name="load-from-emr-steps-create-cluster"></a>

COPY 명령은 Amazon EMR Hadoop 분산 파일 시스템(HDFS)에서 데이터를 로드합니다. Amazon EMR 클러스터를 생성할 때 클러스터의 HDFS로 데이터 파일을 출력하도록 클러스터를 구성합니다.

**Amazon EMR 클러스터를 생성하려면**

1. Amazon Redshift 클러스터와 동일한 AWS 리전에 Amazon EMR 클러스터를 생성합니다.

   Amazon Redshift 클러스터가 VPC에 있는 경우 Amazon EMR 클러스터는 동일한 VPC 그룹에 있어야 합니다. Amazon Redshift 클러스터가 EC2-Classic 모드를 사용하는 경우(즉, VPC에 없는 경우), Amazon EMR 클러스터도 EC2-Classic 모드를 사용해야 합니다. 자세한 내용은 *Amazon Redshift 관리 가이드*의 [Virtual Private Cloud(VPC)의 클러스터 관리](https://docs.aws.amazon.com/redshift/latest/mgmt/managing-clusters-vpc.html) 섹션을 참조하세요.

1. 클러스터의 HDFS로 데이터 파일을 출력하도록 클러스터를 구성합니다. HDFS 파일 이름에는 별표(\$1)나 물음표(?)가 포함되면 안 됩니다.
**중요**  
파일 이름에 별표(\$1)나 물음표(?)가 있으면 안 됩니다.

1. COPY 명령이 실행되는 동안 클러스터를 계속 사용할 수 있도록 Amazon EMR 클러스터 구성에서 **자동 종료(Auto-terminate)** 옵션에 대해 **아니요(No)**를 지정합니다.
**중요**  
COPY가 완료되기 전에 변경되거나 삭제된 데이터 파일이 있다면 예상치 못한 결과가 나오거나 COPY 작업이 실패할 수 있습니다.

1. 클러스터 ID와 메인 퍼블릭 DNS(클러스터를 호스팅하는 Amazon EC2 인스턴스의 엔드포인트)를 적어 둡니다. 이후 단계에서 이 정보를 사용하게 됩니다.

## 3단계: Amazon Redshift 클러스터 퍼블릭 키와 클러스터 노드 IP 주소 검색
<a name="load-from-emr-steps-retrieve-key-and-ips"></a>

각 클러스터 노드의 IP 주소를 사용하여 이러한 IP 주소를 사용하는 Amazon Redshift 클러스터로부터의 액세스를 허용하도록 호스트 보안 그룹을 구성합니다.

**콘솔을 사용하여 Amazon Redshift 클러스터 퍼블릭 키와 클러스터의 클러스터 노드 IP 주소를 검색하려면**

1. Amazon Redshift 관리 콘솔에 액세스합니다.

1. 탐색 창에서 **Clusters**(클러스터) 링크를 선택합니다.

1. 목록에서 해당 인스턴스를 선택합니다.

1. **SSH 처리 설정** 그룹을 찾습니다.

   **클러스터 퍼블릭 키**와 **노드 IP 주소**를 적어 둡니다. 이후 단계에서 사용하게 됩니다.  
![\[클러스터 퍼블릭 키 및 노드 IP 주소를 보여 주는 SSH Ingestion Settings 그룹의 스크린샷입니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/copy-from-ssh-console-2.png)

   3단계의 프라이빗 IP 주소를 사용하여 Amazon Redshift로부터의 연결을 수락하도록 Amazon EC2 호스트를 구성합니다.

Amazon Redshift CLI를 사용하여 클러스터 퍼블릭 키와 클러스터의 클러스터 노드 IP 주소를 검색하려면 describe-clusters 명령을 실행합니다. 예:

```
aws redshift describe-clusters --cluster-identifier <cluster-identifier> 
```

응답에는 ClusterPublicKey 값과 프라이빗 및 퍼블릭 IP 주소 목록이 포함되며, 다음과 비슷합니다.

```
{
    "Clusters": [
        {
            "VpcSecurityGroups": [], 
            "ClusterStatus": "available", 
            "ClusterNodes": [
                {
                    "PrivateIPAddress": "10.nnn.nnn.nnn", 
                    "NodeRole": "LEADER", 
                    "PublicIPAddress": "10.nnn.nnn.nnn"
                }, 
                {
                    "PrivateIPAddress": "10.nnn.nnn.nnn", 
                    "NodeRole": "COMPUTE-0", 
                    "PublicIPAddress": "10.nnn.nnn.nnn"
                }, 
                {
                    "PrivateIPAddress": "10.nnn.nnn.nnn", 
                    "NodeRole": "COMPUTE-1", 
                    "PublicIPAddress": "10.nnn.nnn.nnn"
                }
            ], 
            "AutomatedSnapshotRetentionPeriod": 1, 
            "PreferredMaintenanceWindow": "wed:05:30-wed:06:00", 
            "AvailabilityZone": "us-east-1a", 
            "NodeType": "dc2.large", 
            "ClusterPublicKey": "ssh-rsa AAAABexamplepublickey...Y3TAl Amazon-Redshift", 
             ...
             ...
}
```

Amazon Redshift API를 사용하여 클러스터 퍼블릭 키와 클러스터의 클러스터 노드 IP 주소를 검색하려면 `DescribeClusters` 작업을 사용합니다. 자세한 내용은 *Amazon Redshift CLI Guide*의 [describe-clusters](https://docs.aws.amazon.com/cli/latest/reference/redshift/describe-clusters.html) 또는 Amazon Redshift API Guide의 [DescribeClusters](https://docs.aws.amazon.com/redshift/latest/APIReference/API_DescribeClusters.html) 섹션을 참조하세요.

## 4단계: 각각의 Amazon EC2 호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키 추가
<a name="load-from-emr-steps-add-key-to-host"></a>

호스트가 Amazon Redshift를 인식하고 SSH 연결을 수락하도록 모든 Amazon EMR 클러스터 노드에 대해 각 호스트의 권한 부여된 키 파일에 클러스터 퍼블릭 키를 추가합니다.

**호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키를 추가하려면**

1. SSH 연결을 사용하여 호스트에 액세스합니다.

   SSH를 사용하여 인스턴스에 연결에 대한 자세한 내용은 *Amazon EC2 User Guide*의 [Connect to Your Instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html) 섹션을 참조하세요.

1. 콘솔 또는 CLI 응답 텍스트에서 Amazon Redshift 퍼블릭 키를 복사합니다.

1. 퍼블릭 키의 내용을 복사하여 호스트의 `/home/<ssh_username>/.ssh/authorized_keys` 파일에 붙여 넣습니다. 접두사 "`ssh-rsa`"와 접미사 `Amazon-Redshift`"를 포함하여 완전한 문자열을 포함시킵니다. 예: 

   ```
   ssh-rsa AAAACTP3isxgGzVWoIWpbVvRCOzYdVifMrh… uA70BnMHCaMiRdmvsDOedZDOedZ Amazon-Redshift
   ```

## 5단계: Amazon Redshift 클러스터의 모든 IP 주소를 수락하도록 호스트 구성
<a name="load-from-emr-steps-configure-security-groups"></a>

 호스트 인스턴스로의 인바운드 트래픽을 허용하려면 보안 그룹을 편집하고 각각의 Amazon Redshift 클러스터 노드에 하나의 Inbound 규칙을 추가합니다. **유형**에서 포트 22의 TCP 프로토콜이 포함된 SSH를 선택합니다. **소스**에서 [3단계: Amazon Redshift 클러스터 퍼블릭 키와 클러스터 노드 IP 주소 검색](#load-from-emr-steps-retrieve-key-and-ips)에서 가져온 Amazon Redshift 클러스터 노드 프라이빗 IP 주소를 입력합니다. Amazon EC2 보안 그룹에 규칙 추가에 대한 자세한 내용은 *Amazon EC2 User Guide*의 [Authorizing Inbound Traffic for Your Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html) 섹션을 참조하세요.

## 6단계: COPY 명령을 실행하여 데이터 로드
<a name="load-from-emr-steps-run-copy"></a>

[COPY](r_COPY.md) 명령을 실행하여 Amazon EMR 클러스터에 연결하고 데이터를 Amazon Redshift 테이블에 로드합니다. Amazon EMR 클러스터는 COPY 명령이 완료될 때까지 계속 실행되어야 합니다. 예를 들어 자동 종료되도록 클러스터를 구성하지 마세요.

**중요**  
COPY가 완료되기 전에 변경되거나 삭제된 데이터 파일이 있다면 예상치 못한 결과가 나오거나 COPY 작업이 실패할 수 있습니다.

COPY 명령에서 Amazon EMR 클러스터 ID와 HDFS 파일 경로 및 파일 이름을 지정합니다.

```
COPY sales
FROM 'emr://myemrclusterid/myoutput/part*' CREDENTIALS 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole';
```

와일드카드 문자 별표( `*` )와 물음표( `?` )를 파일 이름 인수의 일부로 사용할 수 있습니다. 예를 들어 `part*`는 파일 `part-0000`, `part-0001` 등등을 로드합니다. 폴더 이름만 지정하면 COPY가 폴더의 모든 파일을 로드하려고 합니다.

**중요**  
와일드카드 문자를 사용하거나 폴더 이름만을 사용하는 경우, 원치 않는 파일이 로드되지 않는지 확인하세요. 그럴 경우, COPY 명령이 실패합니다. 예를 들어 일부 프로세스에서는 로그 파일이 출력 폴더로 로드되는 경우도 있습니다.

# 원격 호스트에서 데이터 로드
<a name="loading-data-from-remote-hosts"></a>

COPY 명령을 사용하면 Amazon EC2 인스턴스나 다른 컴퓨터 같은 하나 이상의 원격 호스트에서 병렬로 파일을 로드할 수 있습니다. COPY는 SSH를 사용하여 원격 호스트에 연결하고 원격 호스트에서 명령을 실행해 텍스트 출력을 생성합니다.

원격 호스트는 Amazon EC2 Linux 인스턴스이거나 SSH 연결을 허용하도록 구성된 다른 Unix 또는 Linux 컴퓨터일 수 있습니다. 이 안내서에서는 원격 호스트가 Amazon EC2 인스턴스라고 가정합니다. 다른 컴퓨터의 절차가 다를 경우, 안내서에서 차이점을 명시합니다.

Amazon Redshift는 여러 호스트에 연결할 수 있으며 각 호스트에 대해 여러 SSH 연결을 열 수 있습니다. Amazon Redshift는 각 연결을 통해 고유한 명령을 전송하여 호스트의 표준 출력에 대한 텍스트 출력을 생성합니다. 그러면 Amazon Redshift가 텍스트 파일을 읽을 때 텍스트 출력을 읽습니다.

## 시작하기 전 준비 사항
<a name="load-from-host-before-you-begin"></a>

시작하기 전에 다음을 갖추고 있어야 합니다.
+ SSH를 사용해 연결할 수 있는, Amazon EC2 인스턴스와 같은 하나 이상의 호스트 시스템.
+ 호스트의 데이터 원본.

  Amazon Redshift 클러스터가 호스트에서 실행되어 텍스트 출력을 생성한다는 명령을 내립니다. 클러스터가 호스트에 연결된 후 COPY 명령이 명령을 실행하고, 호스트의 표준 출력에서 텍스트를 읽으며, 데이터를 병렬로 Amazon Redshift 테이블에 로드합니다. 텍스트 출력은 COPY 명령이 수집할 수 있는 형식이어야 합니다. 자세한 내용은 [입력 데이터 준비](t_preparing-input-data.md) 섹션을 참조하세요.
+ 컴퓨터에서 호스트에 액세스합니다.

  Amazon EC2 인스턴스의 경우 SSH 연결을 사용하여 호스트에 액세스합니다. Amazon Redshift 클러스터의 퍼블릭 키를 호스트의 권한 부여된 키 파일에 추가하려면 호스트에 액세스해야 합니다.
+ 실행 중인 Amazon Redshift 클러스터입니다.

  클러스터를 시작하는 방법에 대한 자세한 내용은 [Amazon Redshift 시작 안내서](https://docs.aws.amazon.com/redshift/latest/gsg/)를 참조하세요.

## 데이터 로드 프로세스
<a name="load-from-host-process"></a>

이 섹션에서는 원격 호스트에서 데이터를 로드하는 프로세스를 단계별로 살펴봅니다. 다음 섹션에서는 각 단계에서 해야 할 일을 자세히 설명합니다.
+ **[1단계: 클러스터 퍼블릭 키와 클러스터 노드 IP 주소 검색](#load-from-host-steps-retrieve-key-and-ips)**

  퍼블릭 키를 사용하면 Amazon Redshift 클러스터 노드가 원격 호스트와의 SSH 연결을 설정할 수 있습니다. 각 클러스터 노드의 IP 주소를 사용하여 이러한 IP 주소를 사용하는 Amazon Redshift 클러스터로부터의 액세스를 허용하도록 호스트 보안 그룹 또는 방화벽을 구성합니다.
+ **[2단계: 호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키 추가](#load-from-host-steps-add-key-to-host)**

  호스트가 Amazon Redshift 클러스터를 인식하고 SSH 연결을 수락하도록 호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키를 추가합니다.
+ **[3단계: Amazon Redshift 클러스터의 모든 IP 주소를 수락하도록 호스트를 구성](#load-from-host-steps-configure-security-groups)** 

  Amazon EC2의 경우 인스턴스의 보안 그룹을 수정하여 Amazon Redshift IP 주소를 수락하도록 입력 규칙을 추가합니다. 다른 호스트의 경우 Amazon Redshift 노드가 원격 호스트와의 SSH 연결을 설정할 수 있도록 방화벽을 수정합니다.
+ **[4단계: 호스트의 퍼블릭 키 가져오기](#load-from-host-steps-get-the-host-key)**

  필요한 경우 Amazon Redshift가 호스트 식별에 퍼블릭 키를 사용해야 한다고 지정할 수 있습니다. 퍼블릭 키를 찾아 텍스트를 매니페스트 파일에 복사해야 합니다.
+ **[5단계: 매니페스트 파일 생성](#load-from-host-steps-create-manifest)** 

  매니페스트는 Amazon Redshift가 호스트에 연결해 데이터를 가져오는 데 필요한 세부 정보가 포함된 JSON 형식의 텍스트 파일입니다.
+ **[6단계: Amazon S3 버킷에 매니페스트 파일 업로드](#load-from-host-steps-upload-manifest)** 

  Amazon Redshift는 매니페스트를 읽고 이 정보를 사용해 원격 호스트에 연결합니다. Amazon S3 버킷이 Amazon Redshift 클러스터와 동일한 리전에 속하지 않는 경우에는 [REGION](copy-parameters-data-source-s3.md#copy-region) 옵션을 사용하여 데이터가 위치한 리전을 지정해야 합니다.
+ **[7단계: COPY 명령을 실행하여 데이터 로드](#load-from-host-steps-run-copy)**

  Amazon Redshift 데이터베이스에서 COPY 명령을 실행하여 Amazon Redshift 테이블로 데이터를 로드합니다.

## 1단계: 클러스터 퍼블릭 키와 클러스터 노드 IP 주소 검색
<a name="load-from-host-steps-retrieve-key-and-ips"></a>

각 클러스터 노드의 IP 주소를 사용하여 이러한 IP 주소를 사용하는 Amazon Redshift 클러스터로부터의 액세스를 허용하도록 호스트 보안 그룹을 구성합니다.

**콘솔을 사용하여 클러스터 퍼블릭 키와 클러스터의 클러스터 노드 IP 주소를 검색하려면**

1. Amazon Redshift 관리 콘솔에 액세스합니다.

1. 탐색 창에서 **Clusters**(클러스터) 링크를 선택합니다.

1. 목록에서 해당 인스턴스를 선택합니다.

1. **SSH 처리 설정** 그룹을 찾습니다.

   **클러스터 퍼블릭 키**와 **노드 IP 주소**를 적어 둡니다. 이후 단계에서 사용하게 됩니다.  
![\[클러스터 퍼블릭 키 및 노드 IP 주소를 보여 주는 SSH Ingestion Settings 그룹의 스크린샷입니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/copy-from-ssh-console-2.png)

   3단계의 IP 주소를 사용하여 Amazon Redshift로부터의 연결을 수락하도록 호스트를 구성합니다. 연결하는 호스트의 유형이 무엇이고 호스트가 VPC에 있는지 여부에 따라 퍼블릭 IP 주소 또는 프라이빗 IP 주소를 사용합니다.

Amazon Redshift CLI를 사용하여 클러스터 퍼블릭 키와 클러스터의 클러스터 노드 IP 주소를 검색하려면 describe-clusters 명령을 실행합니다.

예: 

```
aws redshift describe-clusters --cluster-identifier <cluster-identifier> 
```

 응답에는 ClusterPublicKey와 프라이빗 및 퍼블릭 IP 주소 목록이 포함되며, 다음과 비슷합니다.

```
{
    "Clusters": [
        {
            "VpcSecurityGroups": [], 
            "ClusterStatus": "available", 
            "ClusterNodes": [
                {
                    "PrivateIPAddress": "10.nnn.nnn.nnn", 
                    "NodeRole": "LEADER", 
                    "PublicIPAddress": "10.nnn.nnn.nnn"
                }, 
                {
                    "PrivateIPAddress": "10.nnn.nnn.nnn", 
                    "NodeRole": "COMPUTE-0", 
                    "PublicIPAddress": "10.nnn.nnn.nnn"
                }, 
                {
                    "PrivateIPAddress": "10.nnn.nnn.nnn", 
                    "NodeRole": "COMPUTE-1", 
                    "PublicIPAddress": "10.nnn.nnn.nnn"
                }
            ], 
            "AutomatedSnapshotRetentionPeriod": 1, 
            "PreferredMaintenanceWindow": "wed:05:30-wed:06:00", 
            "AvailabilityZone": "us-east-1a", 
            "NodeType": "dc2.large", 
            "ClusterPublicKey": "ssh-rsa AAAABexamplepublickey...Y3TAl Amazon-Redshift", 
             ...
             ...
}
```

Amazon Redshift API를 사용하여 클러스터 퍼블릭 키와 클러스터의 클러스터 노드 IP 주소를 검색하려면 DescribeClusters 작업을 사용합니다. 자세한 내용은 *Amazon Redshift CLI Guide*의 [describe-clusters](https://docs.aws.amazon.com/cli/latest/reference/redshift/describe-clusters.html) 또는 Amazon Redshift API Guide의 [DescribeClusters](https://docs.aws.amazon.com/redshift/latest/APIReference/API_DescribeClusters.html) 섹션을 참조하세요.

## 2단계: 호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키 추가
<a name="load-from-host-steps-add-key-to-host"></a>

호스트가 Amazon Redshift를 인식하고 SSH 연결을 수락하도록 각 호스트의 권한 부여된 키 파일에 클러스터 퍼블릭 키를 추가합니다.

**호스트의 권한 부여된 키 파일에 Amazon Redshift 클러스터 퍼블릭 키를 추가하려면**

1. SSH 연결을 사용하여 호스트에 액세스합니다.

   SSH를 사용하여 인스턴스에 연결에 대한 자세한 내용은 *Amazon EC2 User Guide*의 [Connect to Your Instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-connect-to-instance-linux.html) 섹션을 참조하세요.

1. 콘솔 또는 CLI 응답 텍스트에서 Amazon Redshift 퍼블릭 키를 복사합니다.

1. 퍼블릭 키의 내용을 복사하여 원격 호스트의 `/home/<ssh_username>/.ssh/authorized_keys` 파일에 붙여 넣습니다. `<ssh_username>`은 매니페스트 파일의 "username" 필드의 값과 일치해야 합니다. 접두사 "`ssh-rsa`"와 접미사 `Amazon-Redshift`"를 포함하여 완전한 문자열을 포함시킵니다. 예: 

   ```
   ssh-rsa AAAACTP3isxgGzVWoIWpbVvRCOzYdVifMrh… uA70BnMHCaMiRdmvsDOedZDOedZ Amazon-Redshift
   ```

## 3단계: Amazon Redshift 클러스터의 모든 IP 주소를 수락하도록 호스트를 구성
<a name="load-from-host-steps-configure-security-groups"></a>

 Amazon EC2 인스턴스 또는 Amazon EMR 클러스터 작업 시 각각의 Amazon Redshift 클러스터 노드로부터의 트래픽을 허용하도록 호스트의 보안 그룹에 인바운드 규칙을 추가합니다. **유형**에서 포트 22의 TCP 프로토콜이 포함된 SSH를 선택합니다. **소스**에, [1단계: 클러스터 퍼블릭 키와 클러스터 노드 IP 주소 검색](#load-from-host-steps-retrieve-key-and-ips)에서 가져온 Amazon Redshift 클러스터 노드 IP 주소를 입력합니다. Amazon EC2 보안 그룹에 규칙 추가에 대한 자세한 내용은 *Amazon EC2 User Guide*의 [Authorizing Inbound Traffic for Your Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html) 섹션을 참조하세요.

프라이빗 IP 주소를 사용하는 경우: 
+ Virtual Private Cloud(VPC)에 없는 Amazon Redshift 클러스터 및 Amazon EC2 -Classic 인스턴스가 있고, 이 둘 모두 동일한 AWS 리전에 있는 경우.
+  VPC에 있는 Amazon Redshift 클러스터 및 Amazon EC2 -VPC 인스턴스가 있고, 이 둘 모두 동일한 AWS 리전 및 동일한 VPC에 있는 경우.

 그렇지 않은 경우에는 퍼블릭 IP 주소를 사용합니다.

VPC에서 Amazon Redshift 사용에 대한 자세한 내용은 *Amazon Redshift 관리 가이드*의 [Virtual Private Cloud(VPC)의 클러스터 관리](https://docs.aws.amazon.com/redshift/latest/mgmt/managing-clusters-vpc.html) 섹션을 참조하세요.

## 4단계: 호스트의 퍼블릭 키 가져오기
<a name="load-from-host-steps-get-the-host-key"></a>

필요한 경우 Amazon Redshift가 호스트를 식별할 수 있도록 매니페스트 파일에서 호스트의 퍼블릭 키를 제공할 수 있습니다. COPY 명령은 호스트 퍼블릭 키가 필요하지 않지만 보안상 이유로 '중간자' 공격 예방을 위해 퍼블릭 키를 사용하는 것이 좋습니다.

호스트의 퍼블릭 키는 다음 위치에서 찾을 수 있습니다. 여기서 `<ssh_host_rsa_key_name>`은 호스트 퍼블릭 키의 고유 이름입니다.

```
:  /etc/ssh/<ssh_host_rsa_key_name>.pub
```

**참고**  
Amazon Redshift는 RSA 키만 지원합니다. DSA 키는 지원되지 않습니다.

5단계에서 매니페스트 파일을 만들 때 퍼블릭 키의 텍스트를 매니페스트 파일의 "Public Key" 필드에 붙여 넣습니다.

## 5단계: 매니페스트 파일 생성
<a name="load-from-host-steps-create-manifest"></a>

COPY 명령은 SSH를 사용하여 다수의 호스트에 연결할 뿐만 아니라 각 호스트마다 SSH 연결을 생성할 수 있습니다. 이렇게 생성된 각 호스트 연결을 통해 명령을 실행하고, 명령을 통해 출력되는 데이터를 병렬 방식으로 테이블에 로드합니다. 매니페스트 파일은 Amazon Redshift가 호스트에 연결하는 데 사용하는 JSON 형식의 텍스트 파일입니다. 매니페스트 파일은 SSH 호스트 엔드포인트를 비롯해 호스트에서 데이터를 Amazon Redshift에 반환할 때 실행하는 명령을 지정합니다. 필요한 경우, 호스트 퍼블릭 키, 로그인 사용자 이름 및 각 항목의 필수 플래그를 포함시킬 수 있습니다.

로컬 컴퓨터에 매니페스트 파일을 생성합니다. 이후 단계에서 파일을 Amazon S3에 업로드합니다.

매니페스트 파일의 형식은 다음과 같습니다.

```
{ 
   "entries": [ 
     {"endpoint":"<ssh_endpoint_or_IP>", 
       "command": "<remote_command>",
       "mandatory":true, 
       "publickey": "<public_key>", 
       "username": "<host_user_name>"}, 
     {"endpoint":"<ssh_endpoint_or_IP>", 
       "command": "<remote_command>",
       "mandatory":true, 
       "publickey": "<public_key>", 
       "username": "host_user_name"} 
    ] 
}
```

매니페스트 파일에는 SSH 연결마다 "entries" 구문이 하나씩 포함됩니다. 각 항목은 단일 SSH 연결을 나타냅니다. 단일 호스트에 다중 연결을, 혹은 다수의 호스트에 다중 연결을 생성할 수 있습니다. 예시와 같이 필드 이름과 값에는 큰따옴표가 필요합니다. 큰따옴표가 필요 없는 유일한 값은 필수 필드의 부울 값 **true** 또는 **false**입니다.

다음은 매니페스트 파일의 필드에 대한 설명입니다.

엔드포인트  
호스트의 URL 주소 또는 IP 주소. 예: `ec2-111-222-333.compute-1.amazonaws.com` 또는 "`22.33.44.56`"

명령   
호스트에 의해 실행되어 텍스트 또는 이진수(gzip, lzop 또는 bzip2) 출력을 생성하는 명령. 명령은 사용자 *"host\$1user\$1name"*이 실행 권한을 갖고 있는 어떤 명령도 될 수 있습니다. 명령은 파일 인쇄처럼 간단할 수도 있고 데이터베이스 쿼리나 스크립트 시작일 수도 있습니다. 출력(텍스트 파일, gzip 이진 파일, lzop 이진 파일 또는 bzip2 이진 파일)은 Amazon Redshift COPY 명령이 수집할 수 있는 형식이어야 합니다. 자세한 내용은 [입력 데이터 준비](t_preparing-input-data.md) 섹션을 참조하세요.

publickey  
(옵션) 호스트의 퍼블릭 키입니다. 퍼블릭 키를 입력하면 Amazon Redshift가 호스트를 식별하는 데 이 키를 사용합니다. 퍼블릭 키를 입력하지 않으면 Amazon Redshift가 호스트를 식별하지 않습니다. 예를 들어 원격 호스트의 퍼블릭 키가 `ssh-rsa AbcCbaxxx…xxxDHKJ root@amazon.com`인 경우, public key 필드에 다음 텍스트를 입력합니다. `AbcCbaxxx…xxxDHKJ` 

mandatory  
(선택적) 연결이 실패하는 경우에 COPY 명령이 실패해야 하는지 여부를 나타냅니다. 기본값은 `false`입니다. Amazon Redshift가 하나 이상 연결에 성공하지 못하면 COPY 명령이 중단됩니다.

사용자 이름  
(옵션) 호스트 시스템에 로그온하고 원격 명령을 실행하기 위해 사용할 사용자 이름입니다. 사용자 로그인 이름은 2단계에서 호스트의 인증 키 파일에 퍼블릭 키를 추가할 때 사용한 로그인 이름과 동일해야 합니다. 기본 사용자 이름은 "redshift"입니다.

다음 예는 동일 호스트에 대한 4개의 연결을 열어 각 연결을 통해 서로 다른 명령을 실행하는 완성된 매니페스트를 보여줍니다.

```
{ 
  "entries": [ 
       {"endpoint":"ec2-184-72-204-112.compute-1.amazonaws.com", 
          "command": "cat loaddata1.txt", 
          "mandatory":true, 
          "publickey": "ec2publickeyportionoftheec2keypair", 
          "username": "ec2-user"}, 
       {"endpoint":"ec2-184-72-204-112.compute-1.amazonaws.com", 
          "command": "cat loaddata2.txt", 
          "mandatory":true, 
          "publickey": "ec2publickeyportionoftheec2keypair", 
          "username": "ec2-user"},
       {"endpoint":"ec2-184-72-204-112.compute-1.amazonaws.com", 
          "command": "cat loaddata3.txt", 
          "mandatory":true, 
          "publickey": "ec2publickeyportionoftheec2keypair", 
          "username": "ec2-user"},
       {"endpoint":"ec2-184-72-204-112.compute-1.amazonaws.com", 
          "command": "cat loaddata4.txt", 
          "mandatory":true, 
          "publickey": "ec2publickeyportionoftheec2keypair", 
          "username": "ec2-user"}
     ] 
}
```

## 6단계: Amazon S3 버킷에 매니페스트 파일 업로드
<a name="load-from-host-steps-upload-manifest"></a>

Amazon S3 버킷에 매니페스트 파일을 업로드합니다. Amazon S3 버킷이 Amazon Redshift 클러스터와 동일한 AWS 리전에 속하지 않는 경우에는 [REGION](copy-parameters-data-source-s3.md#copy-region) 옵션을 사용하여 매니페스트가 위치한 AWS 리전을 지정해야 합니다. Amazon S3 버킷 생성 및 파일 업로드 방법에 대한 자세한 내용은 [Amazon Simple Storage Service 사용 설명서](https://docs.aws.amazon.com/AmazonS3/latest/userguide/)를 참조하세요.

## 7단계: COPY 명령을 실행하여 데이터 로드
<a name="load-from-host-steps-run-copy"></a>

[COPY](r_COPY.md) 명령을 실행하여 호스트에 연결하고 데이터를 Amazon Redshift 테이블에 로드합니다. COPY 명령에서 매니페스트 파일의 명시적 Amazon S3 객체 경로를 지정하고 SSH 옵션을 포함시킵니다. 예를 들면 다음과 같습니다.

```
COPY sales
FROM 's3://amzn-s3-demo-bucket/ssh_manifest'  
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
DELIMITER '|'
SSH;
```

**참고**  
자동 압축을 사용하는 경우 COPY 명령은 두 개의 데이터 읽기를 수행합니다. 즉, 원격 명령을 두 번 실행합니다. 첫 번째 읽기는 압축 분석용 샘플을 제공하기 위한 것이며, 두 번째 읽기가 실제로 데이터를 로드합니다. 원격 명령 2회 실행이 잠재적인 부작용으로 인해 문제를 일으킬 수 있는 경우, 자동 압축을 꺼야 합니다. 자동 압축을 끄려면 COMPUPDATE 옵션을 OFF로 설정하여 COPY 명령을 실행합니다. 자세한 내용은 [자동 압축을 사용하여 테이블 로드](c_Loading_tables_auto_compress.md) 섹션을 참조하세요.

# Amazon DynamoDB 테이블에서 데이터 로드
<a name="t_Loading-data-from-dynamodb"></a>

COPY 명령을 사용하여 단일 Amazon DynamoDB 테이블에서 데이터와 함께 테이블을 로드할 수 있습니다.

**중요**  
데이터를 제공하는 Amazon DynamoDB 테이블은 [REGION](copy-parameters-data-source-s3.md#copy-region) 옵션을 사용하여 Amazon DynamoDB 테이블이 위치한 AWS 리전을 지정하지 않는 한 클러스터와 동일한 AWS 리전에서 생성해야 합니다.

COPY 명령은 Amazon Redshift 대량 병렬 처리(MPP) 아키텍처를 사용하여 Amazon DynamoDB 테이블에서 병렬로 데이터를 읽고 로드합니다. Amazon Redshift 테이블에서 배포 스타일을 설정하면 병렬 처리를 최대한 활용할 수 있습니다. 자세한 내용은 [쿼리 최적화를 위한 데이터 배포](t_Distributing_data.md) 섹션을 참조하세요.

**중요**  
COPY 명령이 Amazon DynamoDB 테이블에서 데이터를 읽을 때 그 결과로 이루어지는 데이터 전송은 해당 테이블의 프로비저닝 처리량의 일부입니다.

과도한 프로비저닝 읽기 처리량 사용을 피하려면 프로덕션 환경에 있는 Amazon DynamoDB 테이블에서 데이터를 로드하지 않는 것이 좋습니다. 프로덕션 테이블에서 데이터를 로드하는 경우에는 사용되지 않는 프로비저닝 처리량의 평균 비율보다 훨씬 낮게 READRATIO 옵션을 설정하는 것이 좋습니다. 낮은 READRATIO 설정은 조절 문제를 최소화하는 데 도움이 됩니다. Amazon DynamoDB 테이블의 전체 프로비저닝 처리량을 사용하려면 READRATIO를 100으로 설정합니다.

COPY 명령은 다음 규칙을 사용하여 DynamoDB 테이블에서 검색된 항목의 속성 이름을 기존 Amazon Redshift 테이블의 열 이름과 일치시킵니다.
+ Amazon Redshift 테이블 열은 대/소문자를 구분하지 않고 Amazon DynamoDB 항목 속성과 일치합니다. DynamoDB 테이블의 항목에 대/소문자만 다른 여러 속성(예: Price와 PRICE)이 포함된 경우, COPY 명령이 실패합니다.
+ Amazon DynamoDB 테이블의 속성과 일치하지 않는 Amazon Redshift 테이블 열은 [COPY](r_COPY.md) 명령의 EMPTYASNULL 옵션에서 지정한 값에 따라 NULL 또는 비어 있는 상태로 로드됩니다.
+ Amazon Redshift 테이블의 열과 일치하지 않는 Amazon DynamoDB 속성은 삭제됩니다. 속성은 일치되기 전에 읽히며, 삭제된 속성도 해당 테이블의 프로비저닝 처리량의 일부를 사용합니다.
+ 스칼라 STRING 및 NUMBER 데이터 형식의 Amazon DynamoDB 속성만 지원됩니다. Amazon DynamoDB BINARY 및 SET 데이터 형식은 지원되지 않습니다. COPY 명령이 지원되지 않는 데이터 형식을 가진 속성을 로드하려고 하는 경우, 명령은 실패합니다. 속성이 Amazon Redshift 테이블 열과 일치하지 않는 경우 COPY는 속성을 로드하려고 하지 않으며 오류를 발생시키지 않습니다.

COPY 명령은 다음 구문을 사용하여 Amazon DynamoDB 테이블에서 데이터를 로드합니다.

```
COPY <redshift_tablename> FROM 'dynamodb://<dynamodb_table_name>'
authorization
readratio '<integer>';
```

*authorization* 값은 Amazon DynamoDB 테이블에 액세스하는 데 필요한 AWS 자격 증명입니다. 이 자격 증명이 사용자와 일치하는 경우 해당 사용자에게 로드되는 Amazon DynamoDB 테이블에 대한 SCAN 및 DESCRIBE 권한이 있어야 합니다.

*authorization* 값은 클러스터가 Amazon DynamoDB 테이블에 액세스하는 데 필요한 AWS 권한 부여를 제공합니다. 권한에는 로드되는 Amazon DynamoDB 테이블에 대한 SCAN 및 DESCRIBE가 포함되어야 합니다. 필요한 권한에 대한 자세한 내용은 [COPY, UNLOAD 및 CREATE LIBRARY 작업을 위한 IAM 권한](copy-usage_notes-access-permissions.md#copy-usage_notes-iam-permissions) 섹션을 참조하세요. 선호되는 인증 방법은 IAM\$1ROLE 파라미터를 지정하고 IAM 역할의 Amazon 리소스 이름(ARN)에 필요한 권한을 제공하는 것입니다. 자세한 내용은 [역할 기반 액세스 제어](copy-usage_notes-access-permissions.md#copy-usage_notes-access-role-based) 섹션을 참조하세요.

IAM\$1ROLE 파라미터를 사용하여 인증하려면 다음 구문을 참조하여 *<aws-account-id>* 및 *<role-name>*을 바꿉니다.

```
IAM_ROLE 'arn:aws:iam::<aws-account-id>:role/<role-name>'
```

다음 예는 IAM 역할을 사용한 인증을 보여 줍니다.

```
COPY favoritemovies 
FROM 'dynamodb://ProductCatalog'
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole';
```

기타 옵션에 대한 자세한 내용은 [권한 부여 파라미터](copy-parameters-authorization.md) 섹션을 참조하세요.

실제로 테이블을 로드하지 않고 데이터를 확인하려면 [COPY](r_COPY.md) 명령과 함께 NOLOAD 옵션을 사용하세요.

다음 예에서는 DynamoDB 테이블 my-favorite-movies-table의 데이터와 함께 FAVORITEMOVIES 테이블을 로드합니다. 읽기 작업은 프로비저닝 처리량의 최대 50%를 사용합니다.

```
COPY favoritemovies FROM 'dynamodb://my-favorite-movies-table' 
IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole' 
READRATIO 50;
```

처리량을 극대화하기 위해 COPY 명령은 클러스터의 컴퓨팅 노드에서 병렬로 Amazon DynamoDB에서 데이터를 로드합니다.

## 자동 압축을 사용한 프로비저닝 처리량
<a name="t_Loading-data-from-dynamodb-provisioned-throughput-with-automatic-compression"></a>

기본적으로 COPY 명령은 압축 인코딩이 없는 빈 대상 테이블을 지정할 때마다 자동 압축을 적용합니다. 자동 압축 분석은 처음에 Amazon DynamoDB 테이블에서 많은 수의 행을 샘플링합니다. 샘플 크기는 COMPROWS 파라미터의 값에 따라 달라집니다. 기본값은 조각당 100,000행입니다.

샘플링 후 샘플 행은 삭제되며 전체 테이블이 로드됩니다. 그 결과, 많은 행을 두 번 읽게 됩니다. 자동 압축의 작동 원리에 대한 자세한 내용은 [자동 압축을 사용하여 테이블 로드](c_Loading_tables_auto_compress.md) 섹션을 참조하세요.

**중요**  
COPY 명령이 샘플링에 사용된 행을 포함하여 Amazon DynamoDB 테이블에서 데이터를 읽을 때 그 결과로 이루어지는 데이터 전송은 해당 테이블의 프로비저닝 처리량의 일부입니다.

## Amazon DynamoDB에서 멀티바이트 데이터 로드
<a name="t_Loading-data-from-dynamodb-loading-multibyte-data-from-amazon-dynamodb"></a>

데이터에 중국어나 키릴 문자 같이 ASCII가 아닌 멀티바이트 문자가 포함되어 있는 경우에는 VARCHAR 열에 데이터를 로드해야 합니다. VARCHAR 데이터 형식은 4바이트 UTF-8 문자를 지원하지만 CHAR 데이터 형식에서는 1바이트 ASCII 문자만 허용되기 때문입니다. Amazon Redshift 테이블에 5바이트 이상의 문자는 로드할 수 없습니다. CHAR 및 VARCHAR에 대한 자세한 내용은 [데이터 타입](c_Supported_data_types.md) 섹션을 참조하세요.

# 데이터가 올바로 로드되었는지 확인
<a name="verifying-that-data-loaded-correctly"></a>

로드 작업이 완료된 후 [STL\$1LOAD\$1COMMITS](r_STL_LOAD_COMMITS.md) 시스템 테이블을 쿼리하여 예상되는 파일이 로드되었는지 확인합니다. 로드에 문제가 있을 경우 전체 트랜잭션을 롤백할 수 있도록 COPY 명령과 로드 확인을 동일한 트랜잭션 내에서 실행합니다.

다음은 TICKIT 데이터베이스의 테이블을 로드하기 위한 항목을 반환하는 쿼리입니다.

```
SELECT query, trim(filename) AS filename, curtime, status
FROM stl_load_commits
WHERE filename like '%tickit%' order by query;


 query |         filename          |          curtime           | status
-------+---------------------------+----------------------------+--------
 22475 | tickit/allusers_pipe.txt  | 2013-02-08 20:58:23.274186 |      1
 22478 | tickit/venue_pipe.txt     | 2013-02-08 20:58:25.070604 |      1
 22480 | tickit/category_pipe.txt  | 2013-02-08 20:58:27.333472 |      1
 22482 | tickit/date2008_pipe.txt  | 2013-02-08 20:58:28.608305 |      1
 22485 | tickit/allevents_pipe.txt | 2013-02-08 20:58:29.99489  |      1
 22487 | tickit/listings_pipe.txt  | 2013-02-08 20:58:37.632939 |      1
 22489 | tickit/sales_tab.txt      | 2013-02-08 20:58:37.632939 |      1
(6 rows)
```

# 입력 데이터 확인
<a name="t_Validating_input_files"></a>

실제로 데이터를 로드하기 전에 Amazon S3 입력 파일 또는 Amazon DynamoDB 테이블의 데이터를 확인하려면 [COPY](r_COPY.md) 명령과 함께 NOLOAD 옵션을 사용합니다. 데이터를 로드할 때 사용할 동일한 COPY 명령 및 옵션과 함께 NOLOAD를 사용합니다. NOLOAD는 데이터를 데이터베이스에 로드하지 않고 모든 데이터의 무결성을 검사합니다. NOLOAD 옵션은 데이터 로드를 시도할 경우 발생하는 모든 오류를 표시합니다.

예를 들어 입력 파일에 잘못된 Amazon S3 경로를 지정하면 Amazon Redshift에서 다음 오류를 표시합니다.

```
ERROR:  No such file or directory
DETAIL:
-----------------------------------------------
Amazon Redshift error:  The specified key does not exist
code:      2
context:   S3 key being read :
location:  step_scan.cpp:1883
process:   xenmaster [pid=22199]
-----------------------------------------------
```

오류 메시지 문제를 해결하려면 [로드 오류 참조](r_Load_Error_Reference.md) 섹션을 참조하세요.

NOLOAD 옵션을 사용하는 예제는 [NOLOAD 옵션을 사용한 CPPY 명령](r_COPY_command_examples.md#r_COPY_command_examples-load-noload-option) 섹션을 참조하세요.

# 자동 압축을 사용하여 테이블 로드
<a name="c_Loading_tables_auto_compress"></a>

데이터 평가에 따라 수동으로 테이블의 열에 압축 인코딩을 적용할 수 있습니다. 또는 COMPUPDATE가 [켜짐(ON)]으로 설정된 COPY 명령을 사용하여 샘플 데이터를 기반으로 압축을 자동으로 분석하고 적용할 수 있습니다.

새 테이블을 만들고 로드할 때 자동 압축을 사용할 수 있습니다. COPY 명령은 압축 분석을 수행합니다. 이미 채워진 테이블에 대해 [ANALYZE COMPRESSION](r_ANALYZE_COMPRESSION.md) 명령을 실행하여 테이블에서 데이터를 로드하거나 압축을 변경하지 않고 압축 분석을 수행할 수도 있습니다. 예를 들어 기존 데이터 정의 언어(DDL) 문을 유지하면서 나중에 사용하기 위해 테이블에서 압축을 분석하려는 경우 ANALYZE COMPRESSION을 실행할 수 있습니다.

자동 압축은 압축 인코딩을 선택할 때 전반적인 성능의 밸런스를 유지합니다. 범위가 제한된 스캔은 정렬 키 열이 동일한 쿼리의 다른 열보다 훨씬 높게 압축된 경우 성능이 떨어질 수 있습니다. 따라서 자동 압축은 정렬 키 열에서 데이터 분석 단계를 건너뛰고 사용자 정의 인코딩 유형을 유지합니다.

인코딩 유형을 명시적으로 정의하지 않은 경우 자동 압축은 RAW 인코딩을 선택합니다. ANALYZE COMPRESSION은 동일하게 동작합니다. 최적의 쿼리 성능을 얻으려면 정렬 키에 RAW를 사용해 보세요.

## 자동 압축 작동 원리
<a name="c_Loading_tables_auto_compress-how-automatic-compression-works"></a>

COMPUPDATE 파라미터가 ON으로 설정된 경우 COPY 명령은 빈 대상 테이블에 COPY 명령을 실행할 때마다 항상 자동 압축을 적용하고 모든 테이블 열에는 RAW 인코딩이 있거나 인코딩이 없습니다.

현재의 압축 인코딩에 상관없이 빈 테이블에 자동 압축을 적용하려면 COMPUPDATE 옵션을 ON으로 설정하여 COPY 명령을 실행합니다. 자동 압축을 끄려면 COMPUPDATE 옵션을 OFF로 설정하여 COPY 명령을 실행합니다.

이미 데이터가 포함되어 있는 테이블에는 자동 압축을 적용할 수 없습니다.

**참고**  
자동 압축 분석이 유의미한 샘플을 생성하려면 로드 데이터에 충분한 행이 필요합니다(조각당 100,000행 이상).

자동 압축은 로드 트랜잭션의 일환으로 백그라운드에서 이러한 작업을 수행합니다.

1. 초기 행 샘플은 입력 파일에서 로드됩니다. 샘플 크기는 COMPROWS 파라미터의 값에 기반합니다. 기본값은 100,000입니다.

1. 각 열마다 압축 옵션이 선택됩니다.

1. 테이블에서 샘플 행이 제거됩니다.

1. 선택한 압축 인코딩을 사용하여 테이블이 다시 생성됩니다.

1. 전체 입력 파일이 로드되고 새 인코딩을 사용하여 압축됩니다.

COPY 명령을 실행한 후에 테이블이 완전히 로드되고 압축되며, 사용할 수 있게 됩니다. 나중에 더 많은 데이터를 로드하는 경우, 추가되는 행은 기존 인코딩에 따라 압축됩니다.

압축 분석만을 수행하려면 ANALYZE COMPRESSION을 실행하는 것이 전체 COPY를 실행하는 것보다 효율적입니다. 그런 다음 결과를 평가하여 자동 압축을 사용할지 수동으로 테이블을 다시 생성할지 결정합니다.

자동 압축은 COPY 명령에만 지원됩니다. 아니면 테이블을 만들 때 수동으로 압축 인코딩을 적용할 수 있습니다. 수동 압축 인코딩에 대한 자세한 내용은 [열 압축으로 저장된 데이터 크기 축소](t_Compressing_data_on_disk.md) 섹션을 참조하세요.

## 자동 압축 예
<a name="r_COPY_COMPRESS_examples"></a>

이 예에서는 TICKIT 데이터베이스에 BIGLIST라고 하는 LISTING 테이블의 사본이 포함되어 있고 이 테이블이 약 300만 개의 행과 함께 로드될 때 자동 압축을 적용하려 한다고 가정합니다.

**테이블을 로드하고 자동으로 압축하려면**

1. 테이블이 비어 있는지 확인합니다. 자동 압축은 비어 있는 테이블에만 적용할 수 있습니다.

   ```
   TRUNCATE biglist;
   ```

1. 단일 COPY 명령을 사용하여 테이블을 로드합니다. 테이블이 비어 있어도 이전의 일부 인코딩이 지정되어 있을 수 있습니다. Amazon Redshift가 압축 분석을 수행하도록 촉진하려면 COMPUPDATE 파라미터를 ON으로 설정합니다.

   ```
   COPY biglist FROM 's3://amzn-s3-demo-bucket/biglist.txt' 
   IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
   DELIMITER '|' COMPUPDATE ON;
   ```

   COMPROWS 옵션이 지정되지 않았기 때문에 기본적인 권장 샘플 크기인 조각당 100,000행이 사용됩니다.

1. 자동으로 선택된 인코딩 체계를 검토하려면 BIGLIST의 새 스키마를 살펴보세요.

   ```
   SELECT "column", type, encoding 
   from pg_table_def where tablename = 'biglist';
   
   
        Column     |            Type             | Encoding 
   ----------------+-----------------------------+----------
    listid         | integer                     | az64
    sellerid       | integer                     | az64
    eventid        | integer                     | az64
    dateid         | smallint                    | none
    numtickets     | smallint                    | az64
    priceperticket | numeric(8,2)                | az64
    totalprice     | numeric(8,2)                | az64
    listtime       | timestamp without time zone | az64
   ```

1. 예상되는 수의 행이 로드되었는지 확인합니다.

   ```
   select count(*) from biglist;
   
   count
   ---------
   3079952
   (1 row)
   ```

나중에 COPY 또는 INSERT 문을 사용하여 이 테이블에 행을 추가하는 경우 동일한 압축 인코딩이 적용됩니다.

# 좁은 테이블의 스토리지 최적화
<a name="c_load_compression_hidden_cols"></a>

열은 극히 적지만 행의 수는 아주 많은 테이블의 경우, 3개의 숨겨진 메타데이터 ID 열(INSERT\$1XID, DELETE\$1XID, ROW\$1ID)이 테이블의 디스크 공간 중 불균형하게 많은 양을 사용합니다.

 숨겨진 열의 압축을 최적화하기 위해서는 가능하다면 단일 COPY 트랜잭션에서 테이블을 로드하세요. 여러 개의 별도의 COPY 명령을 사용하여 테이블을 로드하는 경우, INSERT\$1XID 열이 잘 압축되지 않습니다. 여러 COPY 명령을 사용하는 경우에는 vacuum 작업을 수행해야 하지만 INSERT\$1XID의 압축은 개선되지 않습니다.

# 열 기본값 로드
<a name="c_loading_default_values"></a>

필요한 경우, COPY 명령에서 열 목록을 정의할 수 있습니다. 테이블의 열이 열 목록에서 누락된 경우, COPY는 CREATE TABLE 명령에서 지정된 DEFAULT 옵션이 제공하는 값 또는 DEFAULT 옵션이 지정되지 않은 경우에는 NULL을 사용하여 열을 로드합니다.

NOT NULL로 정의된 열에 COPY가 NULL을 할당하려고 하면 COPY 명령이 실패합니다. DEFAULT 옵션 할당에 대한 자세한 내용은 [CREATE TABLE](r_CREATE_TABLE_NEW.md) 섹션을 참조하세요.

Amazon S3의 데이터 파일에서 로드하는 경우 열 목록의 열은 데이터 파일의 필드와 동일한 순서여야 합니다. 데이터 파일의 필드에 열 목록의 해당 열이 없는 경우, COPY 명령이 실패합니다.

Amazon DynamoDB 테이블에서 로드할 때는 순서가 중요하지 않습니다. Amazon Redshift 테이블의 열과 일치하지 않는 Amazon DynamoDB 속성의 필드는 삭제됩니다.

COPY 명령을 사용하여 DEFAULT 값을 테이블로 로드할 때는 다음의 제한이 적용됩니다.
+ 열 목록에 [IDENTITY](r_CREATE_TABLE_NEW.md#identity-clause) 열이 포함된 경우, [COPY](r_COPY.md) 명령에서 EXPLICIT\$1IDS 옵션도 지정해야 하며, 그렇지 않을 경우, COPY 명령이 실패합니다. 마찬가지로 열 목록에서 IDENTITY 열이 누락되어 있고 EXPLICIT\$1IDS 옵션이 지정된 경우, COPY 명령이 실패합니다.
+ 일정한 열에 대해 평가된 DEFAULT 표현식은 로드된 모든 행에서 동일하므로 RANDOM() 함수를 사용하는 DEFAULT 표현식은 모든 행에 동일한 값을 할당합니다.
+ CURRENT\$1DATE 또는 SYSDATE가 포함된 DEFAULT 표현식은 현재 트랜잭션의 타임스탬프로 설정됩니다.

예를 들어 [COPY 예](r_COPY_command_examples.md)의 "기본값을 사용하여 파일에서 데이터 로드"를 참조하세요.

# 데이터 로드 문제 해결
<a name="t_Troubleshooting_load_errors"></a>

Amazon Redshift 테이블로 데이터를 로드할 때 Amazon S3의 오류, 잘못된 입력 데이터 및 COPY 명령 오류가 발생할 수 있습니다. 다음 섹션에서는 데이터 로드 오류 식별 및 해결에 대한 정보를 제공합니다.

**Topics**
+ [S3 이벤트 통합 및 COPY JOB 오류 문제 해결](s3-integration-troubleshooting.md)
+ [S3ServiceException 오류](s3serviceexception-error.md)
+ [데이터 로드 문제 해결을 위한 시스템 테이블](system-tables-for-troubleshooting-data-loads.md)
+ [멀티바이트 문자 로드 오류](multi-byte-character-load-errors.md)
+ [로드 오류 참조](r_Load_Error_Reference.md)

# S3 이벤트 통합 및 COPY JOB 오류 문제 해결
<a name="s3-integration-troubleshooting"></a>

다음 정보를 사용하여 일반적인 Amazon S3 이벤트 통합 문제 및 Amazon Redshift를 사용한 COPY JOB 문제를 해결하세요.

## S3 이벤트 통합 만들기 실패
<a name="s3-integration-troubleshooting-creation"></a>

S3 이벤트 통합을 만들지 못한 경우 통합의 상태는 `Inactive`입니다. Amazon Redshift 데이터 웨어하우스에서 다음 사항이 올바른지 확인하세요.
+ Amazon Redshift의 대상 네임스페이스에 대해 올바른 권한 있는 위탁자 및 통합 소스를 추가했습니다. [S3 이벤트 통합을 만들기 위한 사전 조건](loading-data-copy-job.md#loading-data-copy-job-prerequisites)을(를) 참조하세요.
+ 소스 Amazon S3 버킷에 올바른 리소스 기반 정책을 추가했습니다. [S3 이벤트 통합을 만들기 위한 사전 조건](loading-data-copy-job.md#loading-data-copy-job-prerequisites)을(를) 참조하세요.

## Amazon S3 데이터가 대상 데이터베이스에 표시되지 않음
<a name="s3-integration-troubleshooting-missing-data"></a>

COPY JOB의 데이터가 표시되지 않으면 다음을 확인합니다.
+ SYS\$1COPY\$1JOB\$1DETAIL을 쿼리하여 Amazon S3 파일이 로드되었는지, 수집이 보류 중인지 또는 오류가 있는지 확인합니다. 자세한 내용은 [SYS\$1COPY\$1JOB\$1DETAIL](SYS_COPY_JOB_DETAIL.md) 섹션을 참조하세요.
+ Amazon S3 파일이 없거나 예기치 않은 대기 시간이 있는 경우 STL\$1ERROR 또는 SYS\$1COPY\$1JOB\$1INFO를 참조합니다. 자격 증명 오류 또는 통합이 비활성 상태임을 암시하는 것이 있는지 찾습니다. 자세한 내용은 [STL\$1ERROR](r_STL_ERROR.md) 및 [SYS\$1COPY\$1JOB\$1INFO](SYS_COPY_JOB_INFO.md) 섹션을 참조하세요.

# S3ServiceException 오류
<a name="s3serviceexception-error"></a>

가장 일반적인 s3ServiceException 오류의 원인은 형식이 잘못 지정되었거나, 잘못된 자격 증명 문자열이 있거나, 서로 다른 AWS 리전에 있는 클러스터와 버킷이 있거나, Amazon S3 권한이 불충분한 경우입니다.

이 섹션에서는 각각의 오류 유형에 대한 문제 해결 정보를 제공합니다.

## 잘못된 자격 증명 문자열
<a name="invalid-credentials-string-error"></a>

자격 증명 문자열의 형식이 잘못 지정된 경우, 다음과 같은 오류 메시지가 표시됩니다.

```
ERROR: Invalid credentials. Must be of the format: credentials 
'aws_access_key_id=<access-key-id>;aws_secret_access_key=<secret-access-key>
[;token=<temporary-session-token>]'
```

자격 증명 문자열에 공백이나 줄 바꿈이 없고 작은따옴표로 묶여 있는지 확인합니다.

## 잘못된 액세스 키 ID
<a name="invalid-access-key-id-error"></a>

액세스 키 ID가 존재하지 않는 경우, 다음과 같은 오류 메시지가 표시됩니다.

```
[Amazon](500310) Invalid operation: S3ServiceException:The AWS Access Key Id you provided does not exist in our records.
```

이것은 복사 및 붙여넣기 오류인 경우가 많습니다. 액세스 키 ID를 올바로 입력했는지 확인합니다. 또한 임시 세션 키를 사용 중인 경우 `token`에 대한 값이 설정되어 있는지 확인합니다.

## 잘못된 보안 액세스 키
<a name="invalid-secret-access-key-error"></a>

보안 액세스 키가 잘못된 경우, 다음과 같은 오류 메시지가 표시됩니다.

```
[Amazon](500310) Invalid operation: S3ServiceException:The request signature we calculated does not match the signature you provided. 
Check your key and signing method.,Status 403,Error SignatureDoesNotMatch
```

이것은 복사 및 붙여넣기 오류인 경우가 많습니다. 보안 액세스 키를 올바로 입력했고 액세스 키 ID에 맞는 키인지 확인합니다.

## 버킷이 다른 리전에 있음
<a name="bucket-in-different-region"></a>

COPY 명령에서 지정된 Amazon S3 버킷은 클러스터와 같은 AWS 리전에 있어야 합니다. Amazon S3 버킷과 클러스터가 서로 다른 리전에 있는 경우 다음과 비슷한 오류 메시지가 표시됩니다.

```
ERROR: S3ServiceException:The bucket you are attempting to access must be addressed using the specified endpoint.
```

Amazon S3 관리 콘솔을 사용하여 버킷을 생성할 때 리전을 선택하거나 Amazon S3 API 또는 CLI를 사용하여 버킷을 생성할 때 엔드포인트를 지정하여 특정 리전에서 Amazon S3 버킷을 생성할 수 있습니다. 자세한 내용은 [COPY와 함께 사용할 파일을 Amazon S3에 업로드](t_uploading-data-to-S3.md) 섹션을 참조하세요.

Amazon S3 리전에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [버킷 액세스](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html#access-bucket-intro)를 참조하세요.

또는 COPY 명령과 함께 [REGION](copy-parameters-data-source-s3.md#copy-region) 옵션을 사용하여 리전을 지정할 수 있습니다.

## 액세스가 거부되었습니다
<a name="s3-access-denied-error"></a>

사용자에게 충분한 권한이 없는 경우, 다음과 같은 오류 메시지가 표시됩니다.

```
ERROR: S3ServiceException:Access Denied,Status 403,Error AccessDenied
```

가능한 원인 중 하나는 보안 인증 정보에 의해 식별되는 사용자가 Amazon S3 버킷에 대한 LIST 및 GET 액세스 권한이 없을 수 있다는 것입니다. 기타 원인을 보려면 *Amazon Simple Storage Service 사용 설명서*의 [Amazon S3의 액세스 거부(403 Forbidden) 오류 해결](https://docs.aws.amazon.com/AmazonS3/latest/userguide/troubleshoot-403-errors.html)을 참조하세요.

버킷에 대한 사용자 액세스를 관리하는 방법에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [Amazon S3의 ID 및 액세스 관리](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html)를 참조하세요.

# 데이터 로드 문제 해결을 위한 시스템 테이블
<a name="system-tables-for-troubleshooting-data-loads"></a>

다음 Amazon Redshift 시스템 테이블은 데이터 로드 문제 해결에 도움이 될 수 있습니다.
+ 특정 로드 도중 발생한 오류를 발견하려면 [STL\$1LOAD\$1ERRORS](r_STL_LOAD_ERRORS.md)를 쿼리합니다.
+ 특정 파일의 로드 시간을 확인하거나 특정 파일이 읽혔는지 보려면 [STL\$1FILE\$1SCAN](r_STL_FILE_SCAN.md)을 쿼리합니다.
+ Amazon S3에서 데이터를 전송하는 중에 발생한 오류의 세부 정보를 찾으려면 [STL\$1S3CLIENT\$1ERROR](r_STL_S3CLIENT_ERROR.md)를 쿼리합니다.

**로드 오류를 찾고 진단하려면**

1. 뷰를 생성하거나 로드 오류에 대한 세부 정보를 반환하는 쿼리를 정의합니다. 다음 예는 STL\$1LOAD\$1ERRORS 테이블을 STV\$1TBL\$1PERM 테이블에 조인하여 테이블 ID를 실제 테이블 이름과 일치시킵니다.

   ```
   create view loadview as
   (select distinct tbl, trim(name) as table_name, query, starttime,
   trim(filename) as input, line_number, colname, err_code,
   trim(err_reason) as reason
   from stl_load_errors sl, stv_tbl_perm sp
   where sl.tbl = sp.id);
   ```

1. COPY가 데이터에 관한 유용한 정보를 반환할 수 있도록 COPY 명령에서 MAXERRORS 옵션을 충분히 큰 값으로 설정합니다. COPY에서 오류가 발생하는 경우, STL\$1LOAD\$1ERRORS 테이블에서 세부 정보를 참조하라고 오류 메시지에 표시됩니다.

1. 오류 세부 정보를 보려면 LOADVIEW 뷰를 쿼리합니다. 예: 

   ```
   select * from loadview where table_name='venue';
   ```

   ```
     tbl   | table_name | query |         starttime          
   --------+------------+-------+----------------------------
    100551 | venue      | 20974 | 2013-01-29 19:05:58.365391 
   
   |     input      | line_number | colname | err_code |       reason
   +----------------+-------------+---------+----------+--------------------
   | venue_pipe.txt |           1 |       0 |     1214 | Delimiter not found
   ```

1. 뷰가 반환하는 정보를 바탕으로 입력 파일이나 로드 스크립트의 문제를 수정합니다. 주의할 몇 가지 일반적인 오류는 다음과 같습니다.
   + 테이블의 데이터 형식과 입력 데이터 필드의 값이 불일치.
   + 테이블의 열 수와 입력 데이터의 필드 수가 불일치.
   + 따옴표의 짝이 맞지 않습니다. Amazon Redshift는 작은따옴표와 큰따옴표를 모두 지원합니다. 그러나 이들 따옴표는 적절히 짝이 맞아야 합니다.
   + 입력 파일의 잘못된 형식의 날짜/시간 데이터.
   + 입력 파일에서 범위를 벗어난 값(숫자 열의 경우).
   + 열의 고유 값 수가 압축 인코딩의 제한을 초과.

# 멀티바이트 문자 로드 오류
<a name="multi-byte-character-load-errors"></a>

CHAR 데이터 형식인 열은 1바이트 UTF-8 문자 127바이트까지 또는 ASCII 문자 세트이기도 한 7F 16진수만을 허용합니다. VARCHAR 열은 최대 4바이트까지 멀티바이트 UTF-8 문자를 허용합니다. 자세한 내용은 [문자 형식](r_Character_types.md) 섹션을 참조하세요.

로드 데이터의 줄에 열 데이터 형식에 맞지 않는 문자가 포함되어 있는 경우, COPY는 오류를 반환하고 STL\$1LOAD\$1ERRORS 시스템 로그 테이블에 오류 번호 1220을 사용하여 행을 기록합니다. ERR\$1REASON 필드에는 잘못된 문자의 바이트 시퀀스가 16진수로 포함되어 있습니다.

로드 데이터의 유효하지 않은 문자를 수정하는 대신 로드 프로세스 도중 유효하지 않은 문자를 대체할 수 있습니다. 유효하지 않은 UTF-8 문자를 대체하려면 COPY 명령에서 ACCEPTINVCHARS 옵션을 지정합니다. ACCEPTINVCHARS 옵션이 설정되면 지정한 문자가 코드 포인트를 대체합니다. ACCEPTINVCHARS 옵션이 설정되지 않은 경우 Amazon Redshift는 문자를 유효한 UTF-8로 수락합니다. 자세한 내용은 [ACCEPTINVCHARS](copy-parameters-data-conversion.md#acceptinvchars) 섹션을 참조하세요.

다음 코드 포인트 목록은 유효한 UTF-8이며 ACCEPTINVCHARS 옵션이 설정되지 않은 경우 COPY 작업은 오류를 반환하지 않습니다. 그러나 이러한 코드 포인트는 유효하지 않은 문자입니다. [ACCEPTINVCHARS](copy-parameters-data-conversion.md#acceptinvchars) 옵션을 사용하여 코드 포인트를 지정한 문자로 바꿀 수 있습니다. 이러한 코드 포인트에는 `0xFDD0`\$1`0xFDEF`의 값 범위와 `FFFE` 또는 `FFFF`로 끝나는 `0x10FFFF`까지의 값이 포함됩니다.
+ `0xFFFE`, `0x1FFFE`, `0x2FFFE`, …, `0xFFFFE`, `0x10FFFE`
+ `0xFFFF`, `0x1FFFF`, `0x2FFFF`, …, `0xFFFFF`, `0x10FFFF`

다음 예는 COPY가 UTF-8 문자 `e0 a1 c7a4`를 CHAR 열로 로드하려 할 때 발생하는 오류 이유를 보여줍니다.

```
Multibyte character not supported for CHAR 
(Hint: Try using  VARCHAR). Invalid char: e0 a1 c7a4
```

오류가 VARCHAR 데이터 형식과 관련된 경우, 유효하지 않은 UTF-8 16진수 시퀀스뿐 아니라 오류 코드도 오류 이유에 포함됩니다. 다음 예는 COPY가 UTF-8 `a4`를 VARCHAR 필드로 로드하려 할 때 발생하는 오류 이유를 보여줍니다.

```
String contains invalid or unsupported UTF-8 codepoints. 
Bad UTF-8 hex sequence: a4 (error 3)
```

다음 표에는 VARCHAR 로드 오류의 설명과 해결 방법 제안이 나와 있습니다. 이런 오류 중 하나가 발생하면 문자를 유효한 UTF-8 코드 시퀀스로 대체하거나 문자를 삭제하세요.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/multi-byte-character-load-errors.html)

# 로드 오류 참조
<a name="r_Load_Error_Reference"></a>

파일에서 데이터를 로드하는 중에 오류가 발생하면 [STL\$1LOAD\$1ERRORS](r_STL_LOAD_ERRORS.md) 테이블을 쿼리하여 오류를 파악하고 가능한 설명을 확인합니다. 다음 표에는 데이터 로드 중에 발생할 수 있는 모든 오류 코드가 나와 있습니다.

## 로드 오류 코드
<a name="r_Load_Error_Reference-load-error-codes"></a>

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/r_Load_Error_Reference.html)

# Amazon S3 버킷에서 자동으로 파일을 복사하기 위해 S3 이벤트 통합 만들기
<a name="loading-data-copy-job"></a>

**참고**  
자동 복사용 미리 보기 릴리스가 종료되었습니다. 따라서 미리 보기 클러스터는 미리 보기 기간 종료 30일 후에 자동으로 제거됩니다. 자동 복사를 계속 사용하려면 다른 Amazon Redshift 클러스터에서 기존 자동 복사 작업을 다시 만드는 것이 좋습니다. 미리 보기 클러스터를 최신 Amazon Redshift 버전으로 업그레이드하는 것은 지원되지 않습니다.

자동 복사 작업을 사용하여 Amazon S3에 저장된 파일에서 Amazon Redshift 테이블로 데이터를 로드할 수 있습니다. Amazon Redshift는 COPY 명령에 지정된 경로에 새 Amazon S3 파일이 추가되는 시기를 감지합니다. 그러면 외부 데이터 수집 파이프라인을 만들지 않고도 COPY 명령이 자동으로 실행됩니다. Amazon Redshift는 로드된 파일을 추적합니다. Amazon Redshift는 COPY 명령당 함께 배치되는 파일 수를 결정합니다. 시스템 뷰에서 결과 COPY 명령을 볼 수 있습니다.

자동 COPY JOB을 만드는 첫 번째 단계는 S3 이벤트 통합을 만드는 것입니다. Amazon S3 소스 버킷에 새 파일이 나타나면 Amazon Redshift는 COPY 명령을 사용하여 데이터베이스로의 파일 로드를 관리합니다.

## S3 이벤트 통합을 만들기 위한 사전 조건
<a name="loading-data-copy-job-prerequisites"></a>

s3 이벤트 통합을 설정하려면 다음 사전 조건이 충족되었는지 확인합니다.
+ Amazon S3 버킷에 여러 Amazon S3 권한을 허용하는 버킷 정책이 있어야 합니다. 예를 들어 다음 예시 정책은 *us-east-1*에서 호스팅되는 리소스 버킷 `amzn-s3-demo-bucket`에 대한 권한을 허용합니다. Amazon S3 버킷과 통합이 모두 동일한 AWS 리전에 있습니다.

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
          {
              "Sid": "Auto-Copy-Policy-01",
              "Effect": "Allow",
              "Principal": {
                  "Service": "redshift.amazonaws.com"
                  },
              "Action": [
                  "s3:GetBucketNotification",
                  "s3:PutBucketNotification",
                  "s3:GetBucketLocation"
              ],
              "Resource": "arn:aws:s3:::amzn-s3-demo-bucket:*",
              "Condition": {
                  "ArnLike": {
                      "aws:SourceArn": "arn:aws:redshift:us-east-1:111122223333:integration:*"
                  },
                  "StringEquals": {
                      "aws:SourceAccount": "111122223333"
                  }
              }
          }
      ]
  }
  ```

------
+ 대상 Amazon Redshift 프로비저닝된 클러스터 또는 Redshift Serverless 네임스페이스에 버킷에 대한 권한이 있어야 합니다. 클러스터 또는 서버리스 네임스페이스와 연결된 IAM 역할에 적절한 권한을 허용하는 IAM 정책이 있는지 확인합니다. 이 정책은 버킷 리소스에 대한 `s3:GetObject`(예: `amzn-s3-demo-bucket`) 버킷 리소스에 대한 `s3:ListBucket` 및 해당 콘텐츠(예: `amzn-s3-demo-bucket/*`)를 모두 허용해야 합니다.

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
          {
              "Sid": "AutoCopyReadId",
              "Effect": "Allow",
              "Action": [
                  "s3:GetObject",
                  "s3:ListBucket"
              ],
              "Resource": [
                  "arn:aws:s3:::amzn-s3-demo-bucket",  
                  "arn:aws:s3:::amzn-s3-demo-bucket/*" 
              ]
          }
      ]
  }
  ```

------

  역할에 대한 신뢰 관계가 있는 IAM 역할에 정책을 추가하는 방법은 다음과 같습니다.

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "redshift.amazonaws.com"
                  ]
              },
              "Action": "sts:AssumeRole"
          }
      ]
  }
  ```

------

  대상 데이터 웨어하우스가 프로비저닝된 클러스터인 경우 Amazon Redshift 콘솔에서 클러스터 세부 정보의 **클러스터 권한** 탭을 사용하여 IAM 역할을 프로비저닝된 클러스터에 연결할 수 있습니다. 프로비저닝된 클러스터에 역할을 연결하는 방법에 대한 자세한 내용은 *Amazon Redshift 관리 안내서*의 [IAM 역할을 클러스터와 연결](https://docs.aws.amazon.com/redshift/latest/mgmt/copy-unload-iam-role-associating-with-clusters.html)을 참조하세요.

  대상 데이터 웨어하우스가 Redshift Serverless인 경우 Redshift Serverless 콘솔에서 네임스페이스 세부 정보의 **보안 및 암호화** 탭을 사용하여 IAM 역할을 서버리스 네임스페이스에 연결할 수 있습니다. 역할을 서버리스 네임스페이스에 연결하는 방법에 대한 자세한 내용은 *Amazon Redshift 관리 안내서*의 [Amazon Redshift Serverless에 권한 부여](https://docs.aws.amazon.com/redshift/latest/mgmt/serverless-security-other-services.html)를 참조하세요.
+ Amazon Redshift 데이터 웨어하우스에는 Amazon S3 버킷을 허용하는 리소스 정책도 있어야 합니다. Amazon Redshift 콘솔을 사용하는 경우 s3 이벤트 통합을 만들 때 Amazon Redshift는이 정책을 Amazon Redshift 데이터 웨어하우스에 추가할 수 있도록 **수정** 옵션을 제공합니다. 직접 리소스 정책을 업데이트하려면 [put-resource-policy](https://docs.aws.amazon.com/cli/latest/reference/redshift/put-resource-policy.html) AWS CLI 명령을 사용할 수 있습니다. 예를 들어 Amazon S3 버킷과의 S3 이벤트 통합을 위해 Amazon Redshift 프로비저닝 클러스터에 리소스 정책을 연결하려면 다음과 유사한 AWS CLI 명령을 실행합니다. 다음 예시에서는 사용자 계정 *123456789012*에 대해 *us-east-1* AWS 리전에 프로비저닝된 클러스터 네임스페이스에 대한 정책을 보여줍니다. 버킷의 이름은 *amzn-s3-demo-bucket*입니다.

  ```
  aws redshift put-resource-policy \
  --policy file://rs-rp.json \
  --resource-arn "arn:aws:redshift: us-east-1:123456789012:namespace/cc4ffe56-ad2c-4fd1-a5a2-f29124a56433"
  ```

  여기서 `rs-rp.json`에 다음 사항이 포함됩니다.

------
#### [ JSON ]

****  

  ```
  {
  	"Version":"2012-10-17",		 	 	 
  	"Statement": [
  		{
  			"Effect": "Allow",
  			"Principal": {
  				"Service": "redshift.amazonaws.com"
  			},
  			"Action": "redshift:AuthorizeInboundIntegration",
  			"Resource": "arn:aws:redshift:us-east-1:123456789012:namespace:cc4ffe56-ad2c-4fd1-a5a2-f29124a56433",
  			"Condition": {
  				"StringEquals": {
  					"aws:SourceArn": "arn:aws:s3:::amzn-s3-demo-bucket",
  					"aws:SourceAccount": 111122223333
  				}
  			}
  		},
  		{
  			"Effect": "Allow",
  			"Principal": {
  				"AWS": "arn:aws:iam::111122223333:role/myRedshiftRole"
  			},
  			"Action": "redshift:CreateInboundIntegration",
  			"Resource": "arn:aws:redshift:us-east-1:123456789012:namespace:cc4ffe56-ad2c-4fd1-a5a2-f29124a56433",
  			"Condition": {
  				"StringEquals": {
  					"aws:SourceArn": "arn:aws:s3:::amzn-s3-demo-bucket",
  					"aws:SourceAccount": 111122223333
  				}
  			}
  		}
  	]
  }
  ```

------

  Amazon S3 버킷과 S3 이벤트 통합을 위해 Redshift Serverless 네임스페이스에 리소스 정책을 연결하려면 다음과 유사한 AWS CLI 명령을 실행합니다. 다음 예시에서는 사용자 계정 *123456789012*의 *us-east-1*에 있는 서버리스 네임스페이스에 AWS 리전 대한 정책을 보여줍니다. 버킷의 이름은 *amzn-s3-demo-bucket*입니다.

  ```
  aws redshift put-resource-policy \
  --policy file://rs-rp.json \
  --resource-arn "arn:aws:redshift-serverless:us-east-1:123456789012:namespace/namespace-1"
  ```

  여기서 `rs-rp.json`에 다음 사항이 포함됩니다.

------
#### [ JSON ]

****  

  ```
  {
  	"Version":"2012-10-17",		 	 	 
  	"Statement": [
  		{
  			"Effect": "Allow",
  			"Principal": {
  				"Service": "redshift.amazonaws.com"
  			},
  			"Action": "redshift:AuthorizeInboundIntegration",
  			"Resource": "arn:aws:redshift-serverless:us-east-1:123456789012:namespace/namespace-1",
  			"Condition": {
  				"StringEquals": {
  					"aws:SourceArn": "arn:aws:s3:::amzn-s3-demo-bucket",
  					"aws:SourceAccount": 111122223333
  	
  				}
  			}
  		},
  		{
  			"Effect": "Allow",
  			"Principal": {
  				"AWS": "arn:aws:iam::123456789012:user/myUser"
  			},
  			"Action": "redshift:CreateInboundIntegration",
  			"Resource": "arn:aws:redshift-serverless:us-east-1:123456789012:namespace/namespace-1",
  			"Condition": {
  				"StringEquals": {
  					"aws:SourceArn": "arn:aws:s3:::amzn-s3-demo-bucket",
  					"aws:SourceAccount": 111122223333
  				}
  			}
  		}
  	]
  }
  ```

------

## S3 이벤트 통합 만들기
<a name="loading-data-copy-job-create-s3-event-integration"></a>

복사 작업을 설정하려면 먼저 S3 이벤트 통합을 정의합니다.

------
#### [ Amazon Redshift console ]

**Amazon Redshift 콘솔에서 Amazon S3 이벤트 통합을 만드는 방법**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/redshiftv2/](https://console.aws.amazon.com/redshiftv2/)에서 Amazon Redshift 콘솔을 엽니다.

1. 왼쪽 탐색 창에서 **S3 이벤트 통합**을 선택합니다.

1. **Amazon S3 이벤트 통합 만들기**를 선택하여 마법사를 열어 자동 복사에 사용할 S3 이벤트 통합을 만듭니다. 소스 Amazon S3 버킷과 대상 Amazon Redshift 데이터 웨어하우스는 동일한 AWS 리전에 있어야 합니다. 통합을 만드는 단계를 진행할 때 다음 정보를 지정합니다.
   + **통합 이름** - 현재 AWS 리전에서 AWS 계정이 소유한 모든 통합의 고유 식별자입니다.
   + **설명** - 나중에 참조할 수 있도록 Amazon S3 이벤트 통합을 설명하는 텍스트입니다.
   + **소스 S3 버킷** - 현재 AWS 계정 및 AWS 리전에 있는 Amazon S3 버킷이며 Amazon Redshift로 데이터를 수집하는 소스입니다.
   + **Amazon Redshift 데이터 웨어하우스** - 통합으로부터 데이터를 수신하는 대상 Amazon Redshift 프로비저닝된 클러스터 또는 Redshift Serverless 작업 그룹입니다.

     대상 Amazon Redshift가 동일한 계정에 있는 경우 대상을 선택할 수 있습니다. 대상이 다른 계정에 있는 경우 **Amazon Redshift 데이터 웨어하우스 ARN**을 지정합니다. 대상에는 승인된 위탁자 및 통합 소스가 포함된 리소스 정책이 있어야 합니다. 대상에 올바른 리소스 정책이 없고 대상이 동일한 계정에 있는 경우 **수정** 옵션을 선택하여 통합 생성 프로세스 중에 리소스 정책을 자동으로 적용할 수 있습니다. 대상이 다른 AWS 계정에 있는 경우 Amazon Redshift 웨어하우스에서 리소스 정책을 수동으로 적용해야 합니다.

1. 최대 50개의 태그 **키**와 선택적 **값** 입력 - 통합에 대한 추가 메타데이터를 제공합니다.

1. **S3 이벤트 통합 만들기**를 선택할 수 있는 검토 페이지가 표시됩니다.

------
#### [ AWS CLI ]

AWS CLI를 사용하여 Amazon S3 이벤트 통합을 만들려면 다음 옵션과 함께 `create-integration` 명령을 사용합니다.
+ `integration-name` - 통합 이름을 지정합니다.
+ `source-arn` - Amazon S3 소스 버킷의 ARN을 지정합니다.
+ `target-arn` - Amazon Redshift 프로비저닝 클러스터 또는 Redshift Serverless 작업 그룹 대상의 네임스페이스 ARN을 지정합니다.

다음 예제에서는 통합 이름, 소스 ARN 및 대상 ARN을 제공하여 통합을 생성합니다. 통합은 암호화되지 않습니다.

```
aws redshift create-integration \
--integration-name s3-integration \
--source-arn arn:aws:s3:us-east-1::s3-example-bucket \
--target-arn arn:aws:redshift:us-east-1:123456789012:namespace:a1b2c3d4-5678-90ab-cdef-EXAMPLE22222
          {
    "IntegrationArn": "arn:aws:redshift:us-east-1:123456789012:integration:a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
    "IntegrationName": "s3-integration",
    "SourceArn": "arn:aws:s3:::s3-example-bucket",
    "SourceType": "s3-event-notifications",
    "TargetArn": "arn:aws:redshift:us-east-1:123456789012:namespace:a1b2c3d4-5678-90ab-cdef-EXAMPLE22222",
    "Status": "creating",
    "Errors": [],
    "CreateTime": "2024-10-09T19:08:52.758000+00:00",
    "Tags": []
}
```

다음 AWS CLI 명령을 사용하여 S3 이벤트 통합을 관리할 수도 있습니다.
+ `delete-integration` - 통합 ARN을 지정하여 S3 이벤트 통합을 삭제합니다.
+ `modify-integration` - 통합 ARN을 지정하여 S3 이벤트 통합의 이름 또는 설명(또는 둘 다)을 변경합니다.
+ `describe-integrations` - 통합 ARN을 지정하여 S3 이벤트 통합의 속성을 봅니다.

이러한 명령에 대한 자세한 내용은 [https://docs.aws.amazon.com/cli/latest/reference/redshift/](https://docs.aws.amazon.com/cli/latest/reference/redshift/)를 참조하세요.

------

그런 다음 Amazon Redshift는 연결된 소스 및 대상, 상태, 연결된 자동 복사 작업의 상태에 대한 정보와 함께 S3 이벤트 통합을 만듭니다. **S3 이벤트 통합**을 선택하고 세부 정보를 표시하도록 통합을 선택하여 Amazon Redshift 콘솔에서 S3 이벤트 통합에 대한 정보를 볼 수 있습니다. 통합은 **내 계정 내**에서 만들어진 것과 **다른 계정에서** 만들어진 것으로 구분됩니다. **내 계정 내** 목록에는 소스와 대상이 동일한 계정에 있는 통합이 표시됩니다. **다른 계정에서** 목록에는 다른 계정에서 소스를 소유한 통합이 표시됩니다.

S3 이벤트 통합을 삭제하면 해당 COPY JOB 상태가 `1`(활성)에서 `0`(비활성/보류)로 변경됩니다. 그러나 해당 COPY JOB은 자동으로 삭제되지 않습니다. 나중에 이름이 같은 COPY JOB을 생성하려고 하면 충돌이 발생할 수 있습니다.

## COPY 작업 만들기 및 모니터링
<a name="loading-data-copy-job-create-s3-autocopy"></a>

통합이 만들어진 후 만든 통합에 대한 **S3 이벤트 통합 세부 정보** 페이지에서 **자동 복사 작업 만들기**를 선택하여 통합에 대한 자동 복사 작업을 만들 수 있는 Amazon Redshift Query Editor V2로 이동합니다. Amazon Redshift는 COPY JOB CREATE 문에서 FROM 절의 버킷을 S3 이벤트 통합에 사용되는 버킷과 매칭합니다. Amazon Redshift Query Editor V2에 대한 자세한 내용은 *Amazon Redshift 관리 안내서*의 [Amazon Redshift Query Editor V2를 사용하여 데이터베이스 쿼리](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2.html)를 참조하세요. 예를 들어 Query Editor V2에서 다음 COPY 명령을 실행하여 Amazon S3 버킷 `s3://amzn-s3-demo-bucket/staging-folder`을 Amazon S3 이벤트 통합에 매칭하는 자동 COPY JOB을 만듭니다.

```
COPY public.target_table
FROM 's3://amzn-s3-demo-bucket/staging-folder'
IAM_ROLE 'arn:aws:iam::123456789012:role/MyLoadRoleName'
JOB CREATE my_copy_job_name
AUTO ON;
```

COPY 작업을 한 번 정의합니다. 향후 실행에도 동일한 파라미터가 사용됩니다.

COPY JOB을 정의하고 관리하려면 권한이 있어야 합니다. COPY JOB에 대한 권한 부여 및 취소에 대한 자세한 내용은 [GRANT](r_GRANT.md) 및 [REVOKE](r_REVOKE.md) 섹션을 참조하세요. COPY JOB에 대한 범위 지정 권한 부여 및 취소에 대한 자세한 내용은 [범위가 지정된 권한 부여](r_GRANT.md#grant-scoped-syntax) 및 [범위가 지정된 권한 취소](r_REVOKE.md#revoke-scoped-permissions) 섹션을 참조하세요.

CREATE, LIST, SHOW, DROP, ALTER 및 RUN 작업에 대한 옵션을 사용하여 로드 작업을 관리합니다. 자세한 내용은 [COPY JOB](r_COPY-JOB.md) 섹션을 참조하세요.

COPY JOB 상태 및 진행률을 확인하기 위해 시스템 뷰를 쿼리할 수 있습니다. 뷰는 다음과 같이 제공됩니다.
+ [SYS\$1COPY\$1JOB](SYS_COPY_JOB.md) - 현재 정의된 각 COPY JOB에 대한 행이 포함됩니다.
+ [SYS\$1COPY\$1JOB\$1DETAIL](SYS_COPY_JOB_DETAIL.md) - 각 COPY JOB에 대해 보류 중인 파일, 오류 파일 및 수집된 파일에 대한 세부 정보를 포함합니다.
+ [SYS\$1COPY\$1JOB\$1INFO](SYS_COPY_JOB_INFO.md) - COPY 작업에 대해 로깅된 메시지를 포함합니다.
+ [SYS\$1LOAD\$1HISTORY](SYS_LOAD_HISTORY.md) - COPY 명령의 세부 정보가 포함됩니다.
+ [SYS\$1LOAD\$1ERROR\$1DETAIL](SYS_LOAD_ERROR_DETAIL.md) - COPY 명령 오류의 세부 정보가 포함됩니다.
+ [SVV\$1COPY\$1JOB\$1INTEGRATIONS](SVV_COPY_JOB_INTEGRATIONS.md) - S3 이벤트 통합에 대한 세부 정보를 포함합니다.
+ [STL\$1LOAD\$1ERRORS](r_STL_LOAD_ERRORS.md) - COPY 명령의 오류가 포함됩니다.
+ [STL\$1LOAD\$1COMMITS](r_STL_LOAD_COMMITS.md) - COPY 명령 데이터 로드 문제를 해결하는 데 사용되는 정보가 포함됩니다.

S3 이벤트 통합 오류 문제 해결에 대한 자세한 내용은 [S3 이벤트 통합 및 COPY JOB 오류 문제 해결](s3-integration-troubleshooting.md) 섹션을 참조하세요.

COPY JOB에 의해 로드된 파일 목록을 가져오려면 먼저 *<job\$1id>*를 대체하고 다음 SQL을 실행하세요.

```
SELECT job_id, job_name, data_source, copy_query, filename, status, curtime
FROM sys_copy_job copyjob
JOIN stl_load_commits loadcommit
ON copyjob.job_id = loadcommit.copy_job_id
WHERE job_id = <job_id>;
```

## 자동 복사를 위한 S3 이벤트 통합을 만들 때 고려 사항
<a name="loading-data-copy-job-considerations"></a>

자동 복사를 사용할 때는 다음을 고려하세요.
+ AWS 계정에서 각 클러스터 또는 작업 그룹에 대해 최대 200개의 COPY JOB을 만들 수 있습니다.
+ 각 Amazon Redshift 대상에 대해 최대 50개의 S3 이벤트 통합을 만들 수 있습니다.
+ 버킷 이름에 마침표(.)가 있는 소스 Amazon S3 버킷과 S3 이벤트 통합을 만들 수 없습니다.
+ 동일한 소스와 대상 간에 하나의 S3 이벤트 통합만 생성할 수 있습니다. 즉, Amazon S3 버킷과 Amazon Redshift 데이터 웨어하우스 간에는 한 번에 하나의 Amazon S3 이벤트 통합만 있을 수 있습니다.
+ 소스 Amazon S3 버킷에 정의된 이벤트 유형 `S3_OBJECT_CREATED`에 대한 기존 이벤트 알림은 있을 수 없습니다. 그러나 S3 이벤트 통합이 생성된 후 더 좁은 범위의 접두사/접미사를 사용하여 Amazon S3 버킷 이벤트 알림을 업데이트할 수 있습니다. 이렇게 하면 다른 대상에 대한 다른 접두사/접미사에 `S3_OBJECT_CREATED`를 구성하여 S3 이벤트 통합과의 충돌을 방지할 수도 있습니다. 자동 복사가 예상대로 실행되지 않는 문제가 발생하는 경우 AWS Support에 문의할 때 해당 기간 내 S3 버킷에 대한 `s3:PutBucketNotificationConfiguration` 작업의 AWS CloudTrail 로그를 준비합니다.

## 지원되는 리전
<a name="loading-data-copy-job-regions"></a>

다음 리전은 자동 복사에 사용할 수 있습니다.


| 리전 | 자동 복사 | 
| --- | --- | 
| 아프리카(케이프타운) | Available | 
| 아시아 태평양(홍콩) | Available | 
| 아시아 태평양(타이베이) | Available | 
| 아시아 태평양(도쿄) | Available | 
| 아시아 태평양(서울) | Available | 
| 아시아 태평양(오사카) | Available | 
| 아시아 태평양(뭄바이) | Available | 
| 아시아 태평양(하이데라바드) | Available | 
| 아시아 태평양(싱가포르) | Available | 
| 아시아 태평양(시드니) | Available | 
| 아시아 태평양(자카르타) | Available | 
| 아시아 태평양(멜버른) | Available | 
| 아시아 태평양(말레이시아) | Available | 
| 아시아 태평양(뉴질랜드) | 사용할 수 없음 | 
| 아시아 태평양(태국) | Available | 
| 캐나다(중부) | Available | 
| 캐나다 서부(캘거리) | Available | 
| 중국(베이징) | Available | 
| 중국(닝샤) | Available | 
| 유럽(프랑크푸르트) | Available | 
| 유럽(취리히) | Available | 
| 유럽(스톡홀름) | Available | 
| 유럽(밀라노) | Available | 
| 유럽(스페인) | Available | 
| 유럽(아일랜드) | Available | 
| 유럽(런던) | Available | 
| 유럽(파리) | Available | 
| 이스라엘(텔아비브) | Available | 
| 중동(UAE) | Available | 
| 중동(바레인) | Available | 
| 멕시코(중부) | Available | 
| 남아메리카(상파울루) | Available | 
| 미국 동부(버지니아 북부) | Available | 
| 미국 동부(오하이오) | Available | 
| 미국 서부(캘리포니아 북부) | Available | 
| 미국 서부(오리건) | Available | 
| AWS GovCloud(미국 동부) | Available | 
| AWS GovCloud(미국 서부) | Available | 

# DML 명령을 사용하여 테이블 로드
<a name="t_Updating_tables_with_DML_commands"></a>

Amazon Redshift는 테이블에서 행을 수정하는 데 사용할 수 있는 표준 데이터 조작 언어(DML) 명령(INSERT, UPDATE, DELETE)을 지원합니다. TRUNCATE 명령을 사용하여 빠른 대량 삭제를 수행할 수도 있습니다.

**참고**  
대량의 데이터를 로드하려면 [COPY](r_COPY.md) 명령을 사용하는 것이 가장 좋습니다. 테이블을 채우는 데 개별적인 INSERT문을 사용하는 방식은 엄청나게 느릴 수 있습니다. 데이터가 다른 Amazon Redshift 데이터베이스 테이블에 이미 있는 경우에는, INSERT INTO ... SELECT FROM 또는 CREATE TABLE AS를 사용하여 성능을 개선할 수 있습니다. 자세한 내용은 [INSERT](r_INSERT_30.md) 또는 [CREATE TABLE AS](r_CREATE_TABLE_AS.md) 섹션을 참조하세요.

테이블에서 변경 전에 비해 상당히 많은 수의 행을 삽입, 업데이트 또는 삭제하는 경우, 작업을 마치면 테이블에 대해 ANALYZE 및 VACUUM 명령을 실행합니다. 애플리케이션에서 작은 변경이 시간이 지나면서 누적되는 경우, 정기적으로 ANALYZE 및 VACUUM 명령이 실행되도록 예약하는 것이 좋습니다. 자세한 내용은 [테이블 분석](t_Analyzing_tables.md) 및 [테이블 Vacuum](t_Reclaiming_storage_space202.md) 섹션을 참조하세요.

**Topics**
+ [새 데이터 업데이트 및 삽입](t_updating-inserting-using-staging-tables-.md)

# 새 데이터 업데이트 및 삽입
<a name="t_updating-inserting-using-staging-tables-"></a>

MERGE 명령을 사용하여 기존 테이블에 새 데이터를 효율적으로 추가할 수 있습니다. 스테이징 테이블을 만든 다음 이 섹션에 설명된 방법 중 하나를 사용하여 스테이징 테이블에서 대상 테이블을 업데이트하여 병합 작업을 수행합니다. MERGE 명령에 대한 자세한 내용은 [MERGE](r_MERGE.md) 섹션을 참조하세요.

[병합 예](merge-examples.md)에서는 TICKIT 데이터 세트라고 하는 Amazon Redshift용 샘플 데이터 세트를 사용합니다. 필수 조건으로 [일반 데이터베이스 작업 시작하기](https://docs.aws.amazon.com/redshift/latest/gsg/database-tasks.html)에서 제공되는 지침에 따라 TICKIT 테이블과 데이터를 설정할 수 있습니다. 샘플 데이터 세트에 대한 자세한 내용은 [샘플 데이터베이스](https://docs.aws.amazon.com/redshift/latest/dg/c_sampledb.html)에서 확인할 수 있습니다.

## 병합 방법 1: 기존 행 교체
<a name="merge-method-replace-existing-rows"></a>

대상 테이블의 모든 열을 덮어쓰는 경우 병합을 수행하는 가장 빠른 방법은 기존 행을 바꾸는 것입니다. 이렇게 하면 업데이트할 행을 내부 조인을 사용하여 삭제하기 때문에 대상 테이블을 한 번만 스캔합니다. 행은 삭제된 후에 스테이징 테이블에서 단일 삽입 작업을 통해 새 행으로 교체됩니다.

다음이 모두 참인 경우, 이 방법을 사용하세요.
+ 대상 테이블과 스테이징 테이블에 동일한 열이 포함되어 있습니다.
+ 대상 테이블 열의 모든 데이터를 스테이징 테이블의 모든 열로 교체하려 합니다.
+ 병합에서 스테이징 테이블의 모든 열을 사용합니다.

이러한 기준 중 하나라도 해당되지 않는 경우 다음 섹션에 설명된 병합 방법 2: MERGE를 사용하지 않고 열 목록 지정을 사용하세요.

스테이징 테이블의 열 일부를 사용하지 않는 경우, 변경되지 않는 행을 WHERE 절을 이용해 배제하여 DELETE 및 INSERT 문을 필터링합니다. 하지만 스테이징 테이블의 열 대부분이 병합에 참여하지 않는다면 이 섹션 후반부에서 설명하는 것처럼 별도의 단계에서 UPDATE와 INSERT를 수행하는 것이 좋습니다.

## 병합 방법 2: MERGE를 사용하지 않고 열 목록 지정
<a name="merge-method-specify-column-list"></a>

전체 행을 덮어쓰는 대신 대상 테이블의 특정 열을 업데이트하려면 이 방법을 사용합니다. 이 방법은 추가 업데이트 단계가 필요하고 MERGE 명령을 사용하지 않기 때문에 이전 방법보다 시간이 오래 걸립니다. 다음 중 참인 것이 있다면 이 방법을 사용하세요.
+ 대상 테이블의 모든 열을 업데이트하는 것이 아닙니다.
+ 스테이징 테이블의 행 대부분이 업데이트에서 사용되지 않습니다.

**Topics**
+ [병합 방법 1: 기존 행 교체](#merge-method-replace-existing-rows)
+ [병합 방법 2: MERGE를 사용하지 않고 열 목록 지정](#merge-method-specify-column-list)
+ [임시 스테이징 테이블 생성](merge-create-staging-table.md)
+ [기존 행을 교체하여 병합 작업 수행](merge-replacing-existing-rows.md)
+ [MERGE 명령을 사용하지 않고 열 목록을 지정하여 병합 작업 수행](merge-specify-a-column-list.md)
+ [병합 예](merge-examples.md)

# 임시 스테이징 테이블 생성
<a name="merge-create-staging-table"></a>

*스테이징 테이블*은 업데이트와 삽입을 포함하여 *대상 테이블*을 변경하는 데 사용될 모든 데이터가 보관되는 임시 테이블입니다.

병합 작업에는 스테이징 테이블과 대상 테이블 간의 조인이 필요합니다. 조인 행을 배치하려면 스테이징 테이블의 분산 키를 대상 테이블의 분산 키와 동일한 열로 설정합니다. 예를 들어 대상 테이블이 외래 키 열을 분산 키로 사용하는 경우, 스테이징 테이블의 분산 키에 동일한 열을 사용하세요. [CREATE TABLE LIKE](r_CREATE_TABLE_NEW.md#create-table-like) 문을 사용하여 스테이징 테이블을 생성하는 경우, 스테이징 테이블은 상위 테이블에서 분산 키를 상속합니다. CREATE TABLE AS 문을 사용하는 경우에는 새 테이블이 분산 키를 상속하지 않습니다. 자세한 내용은 [쿼리 최적화를 위한 데이터 배포](t_Distributing_data.md) 섹션을 참조하세요.

분산 키가 기본 키와 동일하지 않고 병합 작업의 일환으로 분산 키가 업데이트되지 않는 경우, 분산 키 열에서 중복 조인 조건자를 추가하여 배치된 조인을 활성화합니다. 예: 

```
where target.primarykey = stage.primarykey 
and target.distkey = stage.distkey
```

쿼리가 배치된 조인을 사용할지 확인하려면 [EXPLAIN](r_EXPLAIN.md)과 함께 쿼리를 실행하고 모든 조인에서 DS\$1DIST\$1NONE을 확인합니다. 자세한 내용은 [쿼리 계획 평가](c_data_redistribution.md) 섹션을 참조하세요.

# 기존 행을 교체하여 병합 작업 수행
<a name="merge-replacing-existing-rows"></a>

해당 절차에 상세히 설명된 병합 작업을 실행할 때 모든 단계를 포함하되 단일 트랜잭션에서 임시 스테이징 테이블을 생성하거나 삭제할 때는 예외입니다. 임의 단계가 실패하면 트랜잭션이 롤백됩니다. 단일 트랜잭션을 사용하면 커밋의 수도 줄어들어 시간과 자원을 절약할 수 있습니다.

**기존 행을 교체하여 병합 작업을 수행하려면**

1. 다음 유사 코드에 나온 것처럼 스테이징 테이블을 생성한 다음 병합될 데이터로 테이블을 채웁니다.

   ```
   CREATE temp table stage (like target); 
   
   INSERT INTO stage 
   SELECT * FROM source 
   WHERE source.filter = 'filter_expression';
   ```

1.  MERGE를 사용하여 스테이징 테이블과 내부 조인을 수행하여 스테이징 테이블과 일치하는 대상 테이블의 행을 업데이트한 다음 스테이징 테이블과 일치하지 않는 나머지 모든 행을 대상 테이블에 삽입합니다.

    업데이트 및 삽입 작업은 하나의 MERGE 명령으로 실행하는 것이 좋습니다.

   ```
   MERGE INTO target 
   USING stage [optional alias] on (target.primary_key = stage.primary_key)
   WHEN MATCHED THEN 
   UPDATE SET col_name1 = stage.col_name1 , col_name2= stage.col_name2, col_name3 = {expr}
   WHEN NOT MATCHED THEN
   INSERT (col_name1 , col_name2, col_name3) VALUES (stage.col_name1, stage.col_name2, {expr});
   ```

1. 스테이징 테이블을 삭제합니다.

   ```
   DROP TABLE stage;
   ```

# MERGE 명령을 사용하지 않고 열 목록을 지정하여 병합 작업 수행
<a name="merge-specify-a-column-list"></a>

절차에 자세히 설명된 병합 작업을 실행할 때는 모든 단계를 단일 트랜잭션에 포함시키세요. 임의 단계가 실패하면 트랜잭션이 롤백됩니다. 단일 트랜잭션을 사용하면 커밋의 수도 줄어들어 시간과 자원을 절약할 수 있습니다.

**열 목록을 지정하여 병합 작업을 수행하려면**

1. 전체 작업을 단일 트랜잭션 블록에 넣습니다.

   ```
   BEGIN transaction;
   … 
   END transaction;
   ```

1. 다음 유사 코드에 나온 것처럼 스테이징 테이블을 생성한 다음 병합될 데이터로 테이블을 채웁니다.

   ```
   create temp table stage (like target); 
   insert into stage 
   select * from source 
   where source.filter = 'filter_expression';
   ```

1. 스테이징 테이블과의 내부 조인을 사용하여 대상 테이블을 업데이트합니다.
   + UPDATE 절에서 업데이트될 열을 명시적으로 나열합니다.
   + 스테이징 테이블과의 내부 조인을 수행합니다.
   + 분산 키가 기본 키와 다르고 분산 키가 업데이트되지 않는 경우, 분산 키에서 중복 조인을 추가합니다. 쿼리가 배치된 조인을 사용할지 확인하려면 [EXPLAIN](r_EXPLAIN.md)과 함께 쿼리를 실행하고 모든 조인에서 DS\$1DIST\$1NONE을 확인합니다. 자세한 내용은 [쿼리 계획 평가](c_data_redistribution.md) 섹션을 참조하세요.
   + 대상 테이블이 타임스탬프 기준으로 정렬된 경우 대상 테이블에서 범위 제한 스캔을 활용하기 위해 술어를 추가합니다. 자세한 내용은 [Amazon Redshift 쿼리 설계 모범 사례](c_designing-queries-best-practices.md) 섹션을 참조하세요.
   + 병합에서 사용하지 않는 행이 있는 경우, 변경할 행을 필터링하기 위해 절을 추가합니다. 예를 들어 하나 이상의 열에서 부등식 필터를 추가하여 변경되지 않은 행을 제외합니다.
   + 문제가 생기면 모든 것을 롤백할 수 있도록 업데이트 작업, 삭제 작업, 삽입 작업을 단일 트랜잭션 블록에 넣습니다.

    예: 

   ```
   begin transaction;
   
   update target 
   set col1 = stage.col1, 
   col2 = stage.col2, 
   col3 = 'expression' 
   from stage 
   where target.primarykey = stage.primarykey 
   and target.distkey = stage.distkey 
   and target.col3 > 'last_update_time' 
   and (target.col1 != stage.col1 
   or target.col2 != stage.col2 
   or target.col3 = 'filter_expression');
   ```

1. 대상 테이블과의 내부 조인을 사용하여 스테이징 테이블에서 필요 없는 행을 삭제합니다. 대상 테이블의 행 중에는 스테이징 테이블의 행과 이미 일치하는 행도 있고 이전 단계에서 업데이트된 행도 있습니다. 어느 경우건 이 행들은 삽입에 필요하지 않습니다.

   ```
   delete from stage 
   using target 
   where stage.primarykey = target.primarykey;
   ```

1. 스테이징 테이블에서 나머지 행을 삽입합니다. VALUES 절에 2단계에서 UPDATE 문에 사용한 것과 동일한 열 목록을 사용합니다.

   ```
   insert into target
   (select col1, col2, 'expression'
   from stage);
   
   end transaction;
   ```

1. 스테이징 테이블을 삭제합니다.

   ```
   drop table stage;
   ```

# 병합 예
<a name="merge-examples"></a>

다음 예는 병합을 수행하여 SALES 테이블을 업데이트합니다. 첫 번째 예는 대상 테이블에서 모든 행을 삭제한 다음 준비 열에서 삽입하는 보다 간단한 방법을 사용합니다. 두 번째 예는 대상 테이블의 선택된 열에서의 업데이트가 필요하므로 추가 업데이트 단계가 포함됩니다.

[병합 예](#merge-examples)에서는 TICKIT 데이터 세트라고 하는 Amazon Redshift용 샘플 데이터 세트를 사용합니다. 필수 조건으로 [일반 데이터베이스 작업 시작하기](https://docs.aws.amazon.com/redshift/latest/gsg/database-tasks.html) 가이드의 지침에 따라 TICKIT 테이블과 데이터를 설정할 수 있습니다. 샘플 데이터 세트에 대한 자세한 내용은 [샘플 데이터베이스](https://docs.aws.amazon.com/redshift/latest/dg/c_sampledb.html)에서 확인할 수 있습니다.

**데이터 원본 샘플 병합**

이 섹션의 예에는 업데이트와 삽입이 모두 포함된 샘플 데이터 원본이 필요합니다. 예를 위해 SALES 테이블의 데이터를 사용하는 SALES\$1UPDATE라는 이름의 샘플 테이블을 만듭니다. 12월 신규 영업 활동을 나타내는 무작위 데이터로 새 테이블을 채웁니다. 다음에 나오는 예에서는 SALES\$1UPDATE 샘플 테이블을 사용해 스테이징 테이블을 만듭니다.

```
-- Create a sample table as a copy of the SALES table.

create table tickit.sales_update as
select * from tickit.sales;

-- Change every fifth row to have updates.

update tickit.sales_update
set qtysold = qtysold*2,
pricepaid = pricepaid*0.8,
commission = commission*1.1
where saletime > '2008-11-30'
and mod(sellerid, 5) = 0;

-- Add some new rows to have inserts.
-- This example creates a duplicate of every fourth row.

insert into tickit.sales_update
select (salesid + 172456) as salesid, listid, sellerid, buyerid, eventid, dateid, qtysold, pricepaid, commission, getdate() as saletime
from tickit.sales_update
where saletime > '2008-11-30'
and mod(sellerid, 4) = 0;
```

**매칭 키를 기반으로 기존 행을 교체하는 병합 예**

다음 스크립트는 SALES\$1UPDATE 테이블을 사용해 12월 영업 활동의 새 데이터로 SALES 테이블에서 병합 작업을 수행합니다. 이 예제에서는 업데이트가 있는 SALES 테이블의 행을 바꿉니다. 이 예제에서는 판매 수량 및 가격 지불 열을 업데이트하지만 수수료 및 급여 시간은 변경하지 않습니다.

```
MERGE into tickit.sales 
USING tickit.sales_update sales_update  
on ( sales.salesid = sales_update.salesid
and sales.listid = sales_update.listid
and sales_update.saletime > '2008-11-30'
and (sales.qtysold != sales_update.qtysold 
or sales.pricepaid != sales_update.pricepaid))
WHEN MATCHED THEN
update SET qtysold = sales_update.qtysold,
pricepaid = sales_update.pricepaid
WHEN NOT MATCHED THEN 
INSERT (salesid, listid, sellerid, buyerid, eventid, dateid, qtysold , pricepaid, commission, saletime)
values (sales_update.salesid, sales_update.listid, sales_update.sellerid, sales_update.buyerid, sales_update.eventid, 
sales_update.dateid, sales_update.qtysold , sales_update.pricepaid, sales_update.commission, sales_update.saletime);

-- Drop the staging table.
drop table tickit.sales_update;

-- Test to see that commission and salestime were not impacted.
SELECT sales.salesid, sales.commission, sales.salestime, sales_update.commission, sales_update.salestime 
FROM tickit.sales 
INNER JOIN tickit.sales_update sales_update  
ON 
sales.salesid = sales_update.salesid
AND sales.listid = sales_update.listid
AND sales_update.saletime > '2008-11-30'
AND (sales.commission != sales_update.commission 
OR sales.salestime != sales_update.salestime);
```

**MERGE를 사용하지 않고 열 목록을 지정하는 병합 예**

다음 예는 병합 작업을 수행하여 12월 영업 활동의 새 데이터로 SALES를 업데이트합니다. 변경되지 않은 행과 함께 업데이트와 삽입이 모두 포함된 샘플 데이터가 필요합니다. 이 예에서는 QTYSOLD 및 PRICEPAID 열은 업데이트하되 COMMISSION과 SALETIME은 변경하지 않으려 합니다. 다음 스크립트는 SALES\$1UPDATE 테이블을 사용해 SALES 테이블에서 병합 작업을 수행합니다.

```
-- Create a staging table and populate it with rows from SALES_UPDATE for Dec
create temp table stagesales as select * from sales_update
where saletime > '2008-11-30';

-- Start a new transaction
begin transaction;

-- Update the target table using an inner join with the staging table
-- The join includes a redundant predicate to collocate on the distribution key –- A filter on saletime enables a range-restricted scan on SALES

update sales
set qtysold = stagesales.qtysold,
pricepaid = stagesales.pricepaid
from stagesales
where sales.salesid = stagesales.salesid
and sales.listid = stagesales.listid
and stagesales.saletime > '2008-11-30'
and (sales.qtysold != stagesales.qtysold 
or sales.pricepaid != stagesales.pricepaid);
 
-- Delete matching rows from the staging table 
-- using an inner join with the target table

delete from stagesales
using sales
where sales.salesid = stagesales.salesid
and sales.listid = stagesales.listid;

-- Insert the remaining rows from the staging table into the target table
insert into sales
select * from stagesales;

-- End transaction and commit
end transaction;

-- Drop the staging table
drop table stagesales;
```

# 전체 복사 수행
<a name="performing-a-deep-copy"></a>

전체 복사는 대량 삽입을 사용하여 테이블을 다시 생성하고 다시 채움으로써 테이블을 자동으로 정렬합니다. 테이블에 정렬되지 않은 큰 리전이 있는 경우, 전체 복사가 vacuum보다 훨씬 빠릅니다. 딥 카피 작업 중에는 추적할 수 있는 경우에만 동시 업데이트를 수행하는 것이 좋습니다. 프로세스가 완료되면 델타 업데이트를 새 테이블로 옮깁니다. VACUUM 작업은 동시 업데이트를 자동으로 지원합니다.

다음 방법 중 하나를 선택해 원본 테이블의 사본을 만들 수 있습니다.
+ 원본 테이블 DDL을 사용합니다.

  CREATE TABLE DDL을 사용할 수 있는 경우, 가장 빠르고 선호되는 방법입니다. 새 테이블을 만들면 기본 키와 외래 키를 비롯해 모든 테이블 및 열 속성을 지정할 수 있습니다. SHOW TABLE 함수를 사용하여 원본 DDL을 찾을 수 있습니다.
+ CREATE TABLE LIKE를 사용합니다.

  원본 DDL을 사용할 수 없는 경우, CREATE TABLE LIKE를 사용해 원본 테이블을 다시 생성할 수 있습니다. 새 테이블은 상위 테이블의 인코딩, 배포 키, 정렬 키 및 null이 아닌 속성을 상속합니다. 새 테이블은 상위 테이블의 기본 키 및 외래 키 속성은 상속하지 않지만 [ALTER TABLE](r_ALTER_TABLE.md)을 사용해 추가할 수 있습니다.
+ 임시 테이블을 생성하고 원본 테이블을 자릅니다.

  상위 테이블의 기본 키와 외래 키 특성을 유지해야 하는 경우. 상위 테이블에 종속성이 있는 경우 CREATE TABLE ... AS(CTAS)를 사용하여 임시 테이블을 만들 수 있습니다. 그런 다음 원본 테이블을 자르고 임시 테이블을 이용해 원본 테이블을 채웁니다.

  임시 테이블을 사용하면 영구 테이블을 사용하는 경우에 비해 성능이 대폭 향상되지만 데이터가 손실될 위험이 있습니다. 임시 테이블은 자신이 생성된 세션이 끝날 때 자동으로 삭제됩니다. TRUNCATE는 트랜잭션 블록 내에 있더라도 즉시 커밋됩니다. TRUNCATE가 성공했지만 후속 INSERT가 완료되기 전에 세션이 종료되면 데이터가 손실됩니다. 데이터 손실을 허용할 수 없다면 영구 테이블을 사용합니다.

테이블의 복사본을 생성한 후 새 테이블에 대한 액세스 권한을 부여해야 할 수 있습니다. [GRANT](r_GRANT.md)를 사용하여 액세스 권한을 정의할 수 있습니다. 테이블의 모든 액세스 권한을 보고 부여하려면 다음 중 하나여야 합니다.
+  슈퍼 사용자 
+  복사할 테이블의 소유자 
+  테이블의 권한을 볼 수 있는 ACCESS SYSTEM TABLE 권한과, 모든 관련 권한을 부여할 권한이 있는 사용자 

또한 딥 카피가 존재하는 스키마에 대한 사용 권한을 부여해야 할 수도 있습니다. 딥 카피의 스키마가 원본 테이블의 스키마와 다르며 `public` 스키마도 아닌 경우에는 사용 권한을 부여해야 합니다. 사용 권한을 보고 부여하려면 다음 중 하나여야 합니다.
+  슈퍼 사용자 
+  딥 카피의 스키마에 대한 USAGE 권한을 부여할 수 있는 사용자 

**원본 테이블 DDL을 사용하여 전체 복사를 수행하려면**

1. (선택적) `v_generate_tbl_ddl`이라는 스크립트를 실행하여 테이블 DDL을 다시 생성합니다.

1. 원본 CREATE TABLE DDL을 사용하여 테이블 사본을 만듭니다.

1. INSERT INTO … SELECT 문을 사용하여 원본 테이블의 데이터로 사본을 채웁니다.

1. 이전 테이블에 부여된 권한을 확인합니다. 이러한 권한은 SVV\$1RELATION\$1PRIVILEGES 시스템 보기에서 확인할 수 있습니다.

1. 필요한 경우 이전 테이블의 권한을 새 테이블에 부여합니다.

1. 원래 테이블에 권한이 있는 모든 그룹과 사용자에게 사용 권한을 부여합니다. 딥 카피 테이블이 `public` 스키마에 있거나 원본 테이블과 동일한 스키마에 있는 경우에는 이 단계를 수행하지 않아도 됩니다.

1. 원본 테이블을 삭제합니다.

1. ALTER TABLE 문을 사용하여 사본의 이름을 원본 테이블 이름으로 변경합니다.

다음 예는 sample\$1copy라는 이름의 SAMPLE 복제본을 사용하여 SAMPLE 테이블에서 전체 복사를 수행합니다.

```
--Create a copy of the original table in the sample_namespace namespace using the original CREATE TABLE DDL.
create table sample_namespace.sample_copy ( … );

--Populate the copy with data from the original table in the public namespace.
insert into sample_namespace.sample_copy (select * from public.sample);

--Check SVV_RELATION_PRIVILEGES for the original table's privileges.
select * from svv_relation_privileges where namespace_name = 'public' and relation_name = 'sample' order by identity_type, identity_id, privilege_type;

--Grant the original table's privileges to the copy table.
grant DELETE on table sample_namespace.sample_copy to group group1;
grant INSERT, UPDATE on table sample_namespace.sample_copy to group group2;
grant SELECT on table sample_namespace.sample_copy to user1;
grant INSERT, SELECT, UPDATE on table sample_namespace.sample_copy to user2;
         
--Grant usage permission to every group and user that has privileges in the original table.
grant USAGE on schema sample_namespace to group group1, group group2, user1, user2;

--Drop the original table.
drop table public.sample;

--Rename the copy table to match the original table's name.
alter table sample_namespace.sample_copy rename to sample;
```

**CREATE TABLE LIKE를 사용하여 전체 복사를 수행하려면**

1. CREATE TABLE LIKE를 사용하여 새 테이블을 생성합니다.

1. INSERT INTO … SELECT 문을 사용하여 현재 테이블에서 새 테이블로 행을 복사합니다.

1. 이전 테이블에 부여된 권한을 확인합니다. 이러한 권한은 SVV\$1RELATION\$1PRIVILEGES 시스템 보기에서 확인할 수 있습니다.

1. 필요한 경우 이전 테이블의 권한을 새 테이블에 부여합니다.

1. 원래 테이블에 권한이 있는 모든 그룹과 사용자에게 사용 권한을 부여합니다. 딥 카피 테이블이 `public` 스키마에 있거나 원본 테이블과 동일한 스키마에 있는 경우에는 이 단계를 수행하지 않아도 됩니다.

1. 현재 테이블을 삭제합니다.

1. ALTER TABLE 문을 사용하여 새 테이블의 이름을 원본 테이블 이름으로 변경합니다.

다음 예는 CREATE TABLE LIKE를 사용하여 SAMPLE 테이블에서 전체 복사를 수행합니다.

```
--Create a copy of the original table in the sample_namespace namespace using CREATE TABLE LIKE.
create table sameple_namespace.sample_copy (like public.sample);

--Populate the copy with data from the original table.
insert into sample_namespace.sample_copy (select * from public.sample);

--Check SVV_RELATION_PRIVILEGES for the original table's privileges.
select * from svv_relation_privileges where namespace_name = 'public' and relation_name = 'sample' order by identity_type, identity_id, privilege_type;

--Grant the original table's privileges to the copy table.
grant DELETE on table sample_namespace.sample_copy to group group1;
grant INSERT, UPDATE on table sample_namespace.sample_copy to group group2;
grant SELECT on table sample_namespace.sample_copy to user1;
grant INSERT, SELECT, UPDATE on table sample_namespace.sample_copy to user2;
         
--Grant usage permission to every group and user that has privileges in the original table.
grant USAGE on schema sample_namespace to group group1, group group2, user1, user2;

--Drop the original table.
drop table public.sample;

--Rename the copy table to match the original table's name.
alter table sample_namespace.sample_copy rename to sample;
```

**임시 테이블을 생성하고 원본 테이블을 잘라 전체 복사를 수행하려면**

1. CREATE TABLE AS를 사용하여 원본 테이블의 행으로 임시 테이블을 생성합니다.

1. 현재 테이블을 자릅니다.

1. INSERT INTO … SELECT 문을 사용하여 임시 테이블에서 원본 테이블로 행을 복사합니다.

1. 임시 테이블을 삭제합니다.

다음 예는 임시 테이블을 생성하고 원본 테이블을 잘라 SALES 테이블에서 전체 복사를 수행합니다. 원본 테이블은 그대로 유지되므로 복사 테이블에 권한을 부여하지 않아도 됩니다.

```
--Create a temp table copy using CREATE TABLE AS.
create temp table salestemp as select * from sales;

--Truncate the original table.
truncate sales;

--Copy the rows from the temporary table to the original table.
insert into sales (select * from salestemp);

--Drop the temporary table.
drop table salestemp;
```

# 테이블 분석
<a name="t_Analyzing_tables"></a>

ANALYZE 작업은 쿼리 플래너가 최적의 계획을 선택하는 데 사용하는 통계 메타데이터를 업데이트합니다.

대부분의 경우 ANALYZE 명령을 명시적으로 실행할 필요가 없습니다. Amazon Redshift는 워크로드의 변경 사항을 모니터링하고 백그라운드에서 통계를 자동으로 업데이트합니다. 또한 COPY 명령은 빈 테이블로 데이터 로드 시 분석을 자동으로 수행합니다.

테이블 또는 전체 데이터베이스를 명시적으로 분석하려면 [ANALYZE](r_ANALYZE.md) 명령을 실행합니다.

## 자동 분석
<a name="t_Analyzing_tables-auto-analyze"></a>

Amazon Redshift는 데이터베이스를 지속적으로 모니터링하고 백그라운드에서 분석 작업을 자동으로 수행합니다. 시스템 성능에 대한 영향을 최소화하기 위해 자동 분석은 워크로드가 적을 때 실행됩니다.

자동 분석은 기본적으로 활성화되어 있습니다. 자동 분석을 끄려면 클러스터의 파라미터 그룹을 수정하여 `auto_analyze` 파라미터를 **false**로 설정합니다.

처리 시간을 줄이고 전반적인 시스템 성능을 개선하기 위해 Amazon Redshift에서는 수정 범위가 작은 테이블에 대한 자동 분석은 건너뜁니다.

분석 작업은 통계가 최신 상태인 테이블은 건너뜁니다. ETL(추출, 변환, 로드) 워크플로우의 일부로 ANALYZE를 실행하면 자동 분석이 통계가 최신 상태인 테이블을 건너뜁니다. 마찬가지로, 자동 분석이 테이블의 통계를 업데이트한 경우에는 명시적 ANALYZE가 해당 테이블을 건너뜁니다.

## 새 테이블 데이터의 분석
<a name="t_Analyzing_tables-new-tables"></a>

 기본적으로 COPY 명령은 데이터를 빈 테이블로 로드한 후 ANALYZE를 수행합니다. STATUPDATE를 ON으로 설정하면 테이블이 비어 있는지 여부에 상관없이 ANALYZE를 수행하도록 지정할 수 있습니다. STATUPDATE를 OFF로 지정하면 ANALYZE가 수행되지 않습니다. 테이블 소유자 또는 수퍼유저만이 ANALYZE 명령을 실행하거나 STATUPDATE가 ON으로 설정된 상태에서 COPY 명령을 실행할 수 있습니다.

Amazon Redshift는 다음 명령을 사용하여 생성하는 새 테이블을 분석합니다.
+ CREATE TABLE AS (CTAS) 
+ CREATE TEMP TABLE AS 
+ SELECT INTO 

처음 데이터가 로드된 후 분석되지 않은 새 테이블에 대해 쿼리를 실행하면 Amazon Redshift에서는 경고 메시지를 반환합니다. 후속 업데이트 또는 로드 후 테이블을 쿼리하면 경고가 발생하지 않습니다. 분석되지 않은 테이블을 참조하는 쿼리에 대해 EXPLAIN 명령을 실행하면 동일한 경고 메시지가 반환됩니다.

비어 있지 않은 테이블에 데이터를 추가해 테이블의 크기가 크게 변경되면 항상 통계를 명시적으로 업데이트할 수 있습니다. ANALYZE 명령을 실행하거나 COPY 명령과 함께 STATUPDATE ON 옵션을 사용하여 업데이트할 수 있습니다. 마지막 ANALYZE 이후 삽입되거나 삭제된 행의 수에 대한 세부 정보를 보려면 [PG\$1STATISTIC\$1INDICATOR](r_PG_STATISTIC_INDICATOR.md) 시스템 카탈로그 테이블을 쿼리합니다.

[ANALYZE](r_ANALYZE.md) 명령의 범위는 다음 중 하나로 지정할 수 있습니다.
+ 전체 현재 데이터베이스
+ 단일 테이블
+ 단일 테이블의 하나 이상의 특정 열
+ 쿼리에서 조건자로 사용될 수 있는 열

 ANALYZE 명령은 테이블에서 행의 샘플을 가져오고, 몇 가지 계산을 하며, 그 결과로 나온 열 통계를 저장합니다. 기본적으로 Amazon Redshift는 DISTKEY 열에 대해 샘플 패스를 실행하고, 테이블의 다른 모든 열에 대해 또 다른 샘플 패스를 실행합니다. 열의 하위 세트에 대한 통계를 생성하려면 쉼표로 구분된 열 목록을 지정할 수 있습니다. PREDICATE COLUMNS 절과 함께 ANALYZE를 실행해 조건자로 사용되지 않는 열은 건너뛸 수 있습니다.

 ANALYZE 작업은 리소스를 많이 사용하므로 실제로 통계 업데이트가 필요한 테이블과 열에서만 실행하세요. 정기적으로 또는 같은 일정으로 모든 테이블의 모든 열을 분석할 필요는 없습니다. 데이터가 대폭 변경되는 경우, 다음에서 자주 사용되는 열을 분석합니다.
+ 정렬 및 그룹화 작업
+ 조인
+ 쿼리 조건자

Amazon Redshift는 처리 시간을 줄이고 전체 시스템 성능을 높이기 위해 [analyze\$1threshold\$1percent](r_analyze_threshold_percent.md) 파라미터에서 결정하는 대로 변경되는 행 비율이 낮은 테이블은 ANALYZE를 건너뜁니다. 기본적으로 분석 임계값은 10퍼센트로 설정됩니다. [SET](r_SET.md) 명령을 실행하면 현재 세션의 분석 임계값을 변경할 수 있습니다.

빈번히 분석할 필요성이 낮은 열은 큰 VARCHAR 열 등 실제로 결코 쿼리되지 않는 사실과 측정값 및 관련 속성을 나타내는 열입니다. 예를 들어 TICKIT 데이터베이스의 LISTING 테이블을 고려해 보세요.

```
select "column", type, encoding, distkey, sortkey
from pg_table_def where tablename = 'listing';


column         |        type        | encoding | distkey | sortkey 
---------------+--------------------+----------+---------+---------
listid         | integer            | none     | t       | 1       
sellerid       | integer            | none     | f       | 0       
eventid        | integer            | mostly16 | f       | 0       
dateid         | smallint           | none     | f       | 0       
numtickets     | smallint           | mostly8  | f       | 0       
priceperticket | numeric(8,2)       | bytedict | f       | 0       
totalprice     | numeric(8,2)       | mostly32 | f       | 0       
listtime       | timestamp with...  | none     | f       | 0
```

이 테이블이 많은 수의 새 레코드와 함께 매일 로드된다면 쿼리에서 조인 키로 자주 사용되는 LISTID 테이블을 정기적으로 분석해야 합니다. TOTALPRICE와 LISTTIME이 쿼리에서 자주 사용되는 제약이라면 평일에는 항상 이 열들과 분산 키를 분석할 수 있습니다.

```
analyze listing(listid, totalprice, listtime);
```

애플리케이션에서 판매자와 이벤트가 훨씬 정적이고 날짜 ID가 2년 또는 3년만을 포함하는 고정된 날짜 집합을 가리킨다고 가정해 보겠습니다. 이 경우, 이러한 열의 고유한 값은 크게 변하지 않습니다. 하지만 각 고유 값의 인스턴스 수는 꾸준히 증가합니다.

그 밖에도 NUMTICKETS 및 PRICEPERTICKET 지표에 대한 쿼리 주기가 TOTALPRICE 열에 비해 드문 경우를 생각해보겠습니다. 이러한 경우에는 주말마다 한 번 전체 테이블에서 ANALYZE 명령을 실행해 매일 분석되지 않는 5개 열의 통계를 업데이트할 수 있습니다.
<a name="t_Analyzing_tables-predicate-columns"></a>
**조건자 열**  
열 목록을 지정하는 대신 편하게 조건자로 사용될 수 있는 열만 분석하는 방법도 있습니다. 쿼리를 실행할 때 join, filter condition 또는 group by 절에서 사용되는 열은 모두 시스템 카탈로그에서 조건자 열로 표시됩니다. PREDICATE COLUMNS 절을 사용하여 ANALYZE를 실행하면 분석 작업에 다음 기준을 만족하는 열만 포함됩니다.
+ 조건자 열로 표시되는 열
+ 분산 키인 열
+ 정렬 키에 포함되는 열

테이블에서 조건자로 표시되는 열이 하나도 없으면 PREDICATE COLUMNS로 지정되더라도 ANALYZE에 모든 열이 포함됩니다. 조건자 열로 표시되는 열이 없는 이유는 테이블에 대한 쿼리를 아직 실행하지 않았기 때문일 수 있습니다.

워크로드의 쿼리 패턴이 비교적 안정적일 때는 PREDICATE COLUMNS를 사용할 수 있습니다. 다른 열이 조건자로 사용되는 경우가 빈번하여 쿼리 패턴이 가변적일 때 PREDICATE COLUMNS를 사용하면 일시적으로 시간이 경과된(stale) 통계가 나타날 수 있습니다. 시간이 경과된 통계는 최적화되지 못한 쿼리 런타임 계획으로 이어져 런타임이 길어지게 됩니다. 하지만 다음에 PREDICATE COLUMNS를 사용하여 ANALYZE를 실행할 때는 새로운 조건자 열이 포함됩니다.

조건자 열에 대한 세부 정보를 보려면 다음 SQL을 사용하여 PREDICATE\$1COLUMNS라는 이름으로 뷰를 생성하세요.

```
CREATE VIEW predicate_columns AS
WITH predicate_column_info as (
SELECT ns.nspname AS schema_name, c.relname AS table_name, a.attnum as col_num,  a.attname as col_name,
        CASE
            WHEN 10002 = s.stakind1 THEN array_to_string(stavalues1, '||') 
            WHEN 10002 = s.stakind2 THEN array_to_string(stavalues2, '||')
            WHEN 10002 = s.stakind3 THEN array_to_string(stavalues3, '||')
            WHEN 10002 = s.stakind4 THEN array_to_string(stavalues4, '||')
            ELSE NULL::varchar
        END AS pred_ts
   FROM pg_statistic s
   JOIN pg_class c ON c.oid = s.starelid
   JOIN pg_namespace ns ON c.relnamespace = ns.oid
   JOIN pg_attribute a ON c.oid = a.attrelid AND a.attnum = s.staattnum)
SELECT schema_name, table_name, col_num, col_name,
       pred_ts NOT LIKE '2000-01-01%' AS is_predicate,
       CASE WHEN pred_ts NOT LIKE '2000-01-01%' THEN (split_part(pred_ts, '||',1))::timestamp ELSE NULL::timestamp END as first_predicate_use,
       CASE WHEN pred_ts NOT LIKE '%||2000-01-01%' THEN (split_part(pred_ts, '||',2))::timestamp ELSE NULL::timestamp END as last_analyze
FROM predicate_column_info;
```

LISING 테이블에 대해 다음 쿼리를 실행한다고 가정하겠습니다. 단, LISTID, LISTTIME 및 EVENTID는 join, filter 및 group by 절에 사용됩니다.

```
select s.buyerid,l.eventid, sum(l.totalprice)
from listing l
join sales s on l.listid = s.listid
where l.listtime > '2008-12-01'
group by l.eventid, s.buyerid;
```

다음 예와 같이 PREDICATE\$1COLUMNS 뷰에 대한 쿼리를 실행하면 LISTID, EVENTID 및 LISTTIME이 조건자 열로 표시되어 있는 것을 볼 수 있습니다.

```
select * from predicate_columns 
where table_name = 'listing';
```

```
schema_name | table_name | col_num | col_name       | is_predicate | first_predicate_use | last_analyze       
------------+------------+---------+----------------+--------------+---------------------+--------------------
public      | listing    |       1 | listid         | true         | 2017-05-05 19:27:59 | 2017-05-03 18:27:41
public      | listing    |       2 | sellerid       | false        |                     | 2017-05-03 18:27:41
public      | listing    |       3 | eventid        | true         | 2017-05-16 20:54:32 | 2017-05-03 18:27:41
public      | listing    |       4 | dateid         | false        |                     | 2017-05-03 18:27:41
public      | listing    |       5 | numtickets     | false        |                     | 2017-05-03 18:27:41
public      | listing    |       6 | priceperticket | false        |                     | 2017-05-03 18:27:41
public      | listing    |       7 | totalprice     | false        |                     | 2017-05-03 18:27:41
public      | listing    |       8 | listtime       | true         | 2017-05-16 20:54:32 | 2017-05-03 18:27:41
```

통계를 최신 상태로 유지하면 쿼리 플래너가 최적의 계획을 선택할 수 있으므로 쿼리 성능이 향상됩니다. Amazon Redshift는 백그라운드에서 통계를 자동으로 새로 고치며 사용자가 ANALYZE 명령을 명시적으로 실행할 수도 있습니다. ANALYZE를 명시적으로 실행하도록 선택한 경우 다음을 수행합니다.
+ 쿼리를 실행하기 전에 ANALYZE 명령을 실행합니다.
+ 정기적인 로드 또는 업데이트 사이클이 끝날 때마다 일상적으로 데이터베이스에 대해 ANALYZE 명령을 실행합니다.
+ 새로 생성한 모든 테이블과 상당한 변경이 있는 모든 기존 테이블이나 열에 대해 ANALYZE 명령을 실행합니다.
+ 쿼리에서의 사용 및 변경 경향에 따라 테이블과 열의 형식마다 일정을 달리하여 ANALYZE 작업을 실행하는 것을 고려해 보세요.
+ ANALYZE를 실행할 때 시간과 클러스터 리소스를 절약하려면 PREDICATE COLUMNS 절을 사용하세요.

프로비저닝된 클러스터 또는 서버리스 네임스페이스에 스냅샷을 복원하거나 일시 중지된 프로비저닝된 클러스터를 다시 시작한 후에는 ANALYZE 명령을 명시적으로 실행할 필요가 없습니다. 이러한 경우 Amazon Redshift는 시스템 테이블 정보를 보존하므로 수동 ANALYZE 명령이 필요하지 않습니다. Amazon Redshift는 필요에 따라 자동 분석 작업을 계속 실행합니다.

분석 작업은 통계가 최신 상태인 테이블은 건너뜁니다. ETL(추출, 변환, 로드) 워크플로우의 일부로 ANALYZE를 실행하면 자동 분석이 통계가 최신 상태인 테이블을 건너뜁니다. 마찬가지로, 자동 분석이 테이블의 통계를 업데이트한 경우에는 명시적 ANALYZE가 해당 테이블을 건너뜁니다.

## ANALYZE 명령 이력
<a name="c_check_last_analyze"></a>

테이블이나 데이터베이스에서 언제 마지막으로 ANALYZE 명령이 실행되었는지 알면 도움이 됩니다. ANALYZE 명령이 실행될 때 Amazon Redshift는 다음과 비슷한 여러 쿼리를 실행합니다.

```
padb_fetch_sample: select * from table_name
```

STL\$1ANALYZE에 대한 쿼리를 실행하여 분석 작업 이력을 확인합니다. Amazon Redshift가 자동 분석을 사용해 테이블을 분석하면 `is_background` 열이 `t`(true)로 설정됩니다. 그렇지 않으면 `f`(false)로 설정됩니다. 다음은 STV\$1TBL\$1PERM을 조인하여 테이블 이름과 런타임 세부 정보를 표시하는 예입니다.

```
select distinct a.xid, trim(t.name) as name, a.status, a.rows, a.modified_rows, a.starttime, a.endtime
from stl_analyze a 
join stv_tbl_perm t  on t.id=a.table_id
where name = 'users'
order by starttime;


xid    | name  | status          | rows  | modified_rows | starttime           | endtime            
-------+-------+-----------------+-------+---------------+---------------------+--------------------
  1582 | users | Full            | 49990 |         49990 | 2016-09-22 22:02:23 | 2016-09-22 22:02:28
244287 | users | Full            | 24992 |         74988 | 2016-10-04 22:50:58 | 2016-10-04 22:51:01
244712 | users | Full            | 49984 |         24992 | 2016-10-04 22:56:07 | 2016-10-04 22:56:07
245071 | users | Skipped         | 49984 |             0 | 2016-10-04 22:58:17 | 2016-10-04 22:58:17
245439 | users | Skipped         | 49984 |          1982 | 2016-10-04 23:00:13 | 2016-10-04 23:00:13
(5 rows)
```

또는 모든 트랜잭션에서 실행된, ANALYZE 명령이 포함된 모든 문을 반환하는 보다 복잡한 쿼리를 실행할 수도 있습니다.

```
select xid, to_char(starttime, 'HH24:MM:SS.MS') as starttime,
datediff(sec,starttime,endtime ) as secs, substring(text, 1, 40)
from svl_statementtext
where sequence = 0
and xid in (select xid from svl_statementtext s where s.text like 'padb_fetch_sample%' )
order by xid desc, starttime;

xid  |  starttime   | secs |                  substring
-----+--------------+------+------------------------------------------
1338 | 12:04:28.511 |    4 | Analyze date
1338 | 12:04:28.511 |    1 | padb_fetch_sample: select count(*) from
1338 | 12:04:29.443 |    2 | padb_fetch_sample: select * from date
1338 | 12:04:31.456 |    1 | padb_fetch_sample: select * from date
1337 | 12:04:24.388 |    1 | padb_fetch_sample: select count(*) from
1337 | 12:04:24.388 |    4 | Analyze sales
1337 | 12:04:25.322 |    2 | padb_fetch_sample: select * from sales
1337 | 12:04:27.363 |    1 | padb_fetch_sample: select * from sales
...
```

# 테이블 Vacuum
<a name="t_Reclaiming_storage_space202"></a>

Amazon Redshift는 백그라운드의 테이블에서 VACUUM DELETE 작업을 자동으로 정렬하고 수행할 수 있습니다. 로드 또는 일련의 증분적 업데이트 후 테이블을 정리하기 위해 전체 데이터베이스나 개별 테이블에 대해 [VACUUM](r_VACUUM_command.md) 명령을 실행할 수도 있습니다.

**참고**  
필요한 테이블 권한이 있는 사용자만 테이블을 유효하게 정리(vacuum)할 수 있습니다. 필요한 테이블 권한 없이 VACUUM을 실행할 경우 작업은 성공적으로 완료되지만 아무런 효과도 없습니다. VACUUM을 유요하게 실행하기 위한 유효한 테이블 권한 목록은 [VACUUM](r_VACUUM_command.md) 섹션을 참조하세요.  
이러한 이유로 필요에 따라 개별 테이블에 대해 VACUUM을 실행하는 것이 좋습니다. 또한 전체 데이터베이스에 대해 vacuum을 실행하면 비용이 많이 필요하므로 이 방법을 권장합니다.

## 자동 테이블 정렬
<a name="automatic-table-sort"></a>

Amazon Redshift는 백그라운드에서 데이터를 자동으로 정렬하여 정렬 키 순서대로 테이블 데이터를 유지합니다. Amazon Redshift는 스캔 쿼리를 추적하여 정렬이 유용한 테이블 섹션을 결정합니다. 또한 Amazon Redshift는 동시성 조정 클러스터에서 스캔 쿼리를 추적합니다. Amazon Redshift 데이터 공유를 사용하는 다중 클러스터 아키텍처의 경우 Amazon Redshift는 여러 리전의 클러스터/작업 그룹을 포함하여 데이터 메시의 소비자 클러스터/작업 그룹에서 시작된 스캔 쿼리도 추적합니다. 기본 클러스터, 동시성 조정 클러스터 및 소비자 클러스터의 스캔 통계가 집계되어 정렬의 이점을 누릴 테이블 섹션을 결정합니다.

시스템의 로드에 따라 Amazon Redshift가 자동으로 정렬을 시작합니다. 이 자동 정렬은 데이터를 정렬 키 순서로 유지하기 위해 VACUUM 명령을 실행할 필요성을 줄입니다. 예를 들어 대량의 데이터 로드 후 정렬 키 순서로 전체 정렬된 데이터가 필요한 경우에도 VACUUM 명령을 수동으로 실행할 수 있습니다. 테이블이 VACUUM SORT 실행을 통해 이익을 얻을 수 있는지 확인하려면 [SVV\$1TABLE\$1INFO](r_SVV_TABLE_INFO.md)의 `vacuum_sort_benefit` 열을 모니터링하세요.

Amazon Redshift는 각 테이블에서 정렬 키를 사용하는 스캔 쿼리를 추적합니다. Amazon Redshift는 각 테이블에 대한 데이터 스캔 및 필터링 개선의 최대 비율을 추정합니다(테이블이 전체 정렬된 경우). 이 추정값은 `vacuum_sort_benefit`의 [SVV\$1TABLE\$1INFO](r_SVV_TABLE_INFO.md) 열에서 볼 수 있습니다. 이 열을 `unsorted` 열과 함께 사용하면 테이블에서 VACUUM SORT를 수동으로 실행하여 쿼리가 이익을 얻을 수 있는 시기를 결정할 수 있습니다. 이 `unsorted` 열은 테이블의 물리적 정렬 순서를 반영합니다. `vacuum_sort_benefit` 열은 VACUUM SORT를 수동으로 실행하여 테이블 정렬의 영향을 지정합니다.

예를 들어 다음 쿼리를 고려해 보세요.

```
select "table", unsorted,vacuum_sort_benefit from svv_table_info order by 1;
```

```
 table | unsorted | vacuum_sort_benefit 
-------+----------+---------------------
 sales |    85.71 |                5.00
 event |    45.24 |               67.00
```

테이블 "sales"의 경우 테이블의 \$186%가 물리적으로 정렬되지 않은 경우에도 86%의 정렬되지 않은 테이블로부터 얻는 쿼리 성능 영향은 5%에 불과합니다. 이는 쿼리에서 테이블의 일부에만 액세스하거나 테이블에 액세스하는 쿼리가 거의 없기 때문일 수 있습니다. “event” 테이블의 경우, 테이블은 \$145%가 물리적으로 정렬되지 않았습니다. 그러나 쿼리 성능 영향이 67%라는 의미는 쿼리에서 테이블의 많은 부분에 액세스하거나 테이블에 액세스하는 쿼리 수가 많음을 나타냅니다. "event" 테이블은 VACUUM SORT를 실행할 때 이익을 얻을 가능성이 있습니다.

## 자동 vacuum 삭제
<a name="automatic-table-delete"></a>

삭제를 수행하면 행이 삭제 표시되지만 제거되지는 않습니다. Amazon Redshift는 데이터베이스 테이블에서 삭제된 행 수를 기준으로 백그라운드에서 VACUUM DELETE 작업을 자동으로 실행합니다. Amazon Redshift는 로드가 감소한 기간 동안 VACUUM DELETE가 실행되도록 예약하고 부하가 많은 기간 동안 작업을 일시 중지합니다.

**Topics**
+ [자동 테이블 정렬](#automatic-table-sort)
+ [자동 vacuum 삭제](#automatic-table-delete)
+ [VACUUM 빈도](#vacuum-frequency)
+ [정렬 단계 및 병합 단계](#vacuum-stages)
+ [vacuum 임계값](#vacuum-sort-threshold)
+ [vacuum 유형](#vacuum-types)
+ [Vacuum 시간 최소화](vacuum-managing-vacuum-times.md)

## VACUUM 빈도
<a name="vacuum-frequency"></a>

일관된 쿼리 성능을 유지하기 위해서는 필요할 때마다 자주 vacuum을 수행해야 합니다. VACUUM 명령을 얼마나 자주 실행할지 결정할 때는 다음 요인을 고려하세요.
+ 저녁이나 지정된 데이터베이스 관리 기간 같이 클러스터에서의 활동이 최소일 것으로 예상되는 기간에 VACUUM을 실행합니다.
+ 유지 관리 기간 외 시간에 VACUUM 명령을 실행합니다. 자세한 내용은 [유지 관리 기간 관련 일정](https://docs.aws.amazon.com/redshift/latest/dg/c_best-practices-avoid-maintenance.html)을 참조하세요.
+ 정렬되지 않은 리전이 많으면 vacuum 시간이 길어집니다. vacuum을 연기하면 다시 정리해야 하는 데이터가 많아지기 때문에 vacuum에 더 많은 시간이 소요됩니다.
+ VACUUM은 I/O를 많이 사용하는 작업이므로 vacuum 완료까지 걸리는 시간이 길어질수록 클러스터에서 실행되는 동시 쿼리와 그 밖의 데이터베이스 작업에 미치는 영향이 커집니다.
+ 인터리브 정렬을 사용하는 테이블의 경우, VACUUM 시간이 길어집니다. 인터리브 테이블을 다시 정렬해야 하는지 평가하려면 [SVV\$1INTERLEAVED\$1COLUMNS](r_SVV_INTERLEAVED_COLUMNS.md) 보기를 쿼리합니다.

## 정렬 단계 및 병합 단계
<a name="vacuum-stages"></a>

Amazon Redshift는 2단계로 vacuum 작업을 수행합니다. 먼저 정렬되지 않은 리전의 행을 정렬한 다음 필요할 경우 테이블 끝에 있는 새로 정렬된 행을 기존의 행과 병합합니다. 큰 테이블을 vacuum하는 경우, vacuum 작업은 증분적 정렬 후 병합으로 구성되는 일련의 단계로 진행됩니다. 작업이 실패하거나 vacuum 도중 Amazon Redshift가 오프라인 상태가 되는 경우 부분적으로 vacuum된 테이블이나 데이터베이스는 일관된 상태가 되지만 vacuum 작업을 수동으로 다시 시작해야 합니다. 증분적 정렬은 손실되지만 실패 전에 커밋된 병합된 행들은 다시 vacuum할 필요가 없습니다. 정렬되지 않은 리전이 클 경우, 상당한 시간을 손해 볼 수 있습니다. 정렬 및 병합 단계에 대한 자세한 내용은 [병합된 행의 볼륨 줄이기](vacuum-managing-vacuum-times.md#vacuum-managing-volume-of-unmerged-rows) 섹션을 참조하세요.

테이블이 vacuum되는 동안 사용자는 테이블에 액세스할 수 있습니다. 테이블이 vacuum되는 중에도 쿼리 및 쓰기 작업을 수행할 수 있지만 DML과 vacuum이 동시에 실행되고 있을 때는 두 작업 모두 시간이 더 소요될 수 있습니다. vacuum 도중에 UPDATE 및 DELETE 문을 실행하는 경우 시스템 성능이 저하될 수 있습니다. 증분적 병합은 동시적인 UPDATE 작업과 DELETE 작업을 일시적으로 차단하며 UPDATE 작업과 DELETE 작업은 해당 테이블에서 증분적 병합 단계를 차단합니다. ALTER TABLE 같은 DDL 작업은 테이블의 vacuum 작업이 끝날 때까지 차단됩니다.

**참고**  
VACUUM에 대한 다양한 수정자가 작동 방식을 제어합니다. 이를 사용하여 현재 요구 사항에 맞게 vacuum 작업을 조정할 수 있습니다. 예를 들어 VACUUM RECLUSTER를 사용하면 전체 병합 작업을 수행하지 않아 vacuum 작업이 단축됩니다. 자세한 내용은 [VACUUM](r_VACUUM_command.md) 섹션을 참조하세요.

## vacuum 임계값
<a name="vacuum-sort-threshold"></a>

기본적으로 VACUUM은 테이블 행의 95% 이상이 이미 정렬된 테이블에 대해서는 정렬 단계를 건너뜁니다. 정렬 단계를 건너뛰면 VACUUM 성능을 상당히 개선할 수 있습니다. 단일 테이블의 기본 정렬 임계값을 변경하려면 VACUUM 명령을 실행할 때 테이블 이름과 TO *threshold* PERCENT 파라미터를 포함시킵니다.

## vacuum 유형
<a name="vacuum-types"></a>

다양한 vacuum 유형에 대한 자세한 내용은 [VACUUM](r_VACUUM_command.md) 섹션을 참조하세요.

# Vacuum 시간 최소화
<a name="vacuum-managing-vacuum-times"></a>

 Amazon Redshift는 백그라운드에서 자동으로 데이터를 정렬하고 VACUUM DELETE를 실행합니다. 이렇게 하면 VACUUM 명령을 실행할 필요성이 줄어듭니다. Vacuum은 시간이 많이 걸릴 수 있는 프로세스입니다. 데이터의 성격에 따라 다르지만, Vacuum 시간을 최소화하려면 다음과 같은 방식을 따르는 것이 좋습니다.

**Topics**
+ [reindex 실행 여부 결정](#r_vacuum-decide-whether-to-reindex)
+ [정렬되지 않은 리전 크기 줄이기](#r_vacuum_diskspacereqs)
+ [병합된 행의 볼륨 줄이기](#vacuum-managing-volume-of-unmerged-rows)
+ [정렬 키 순서로 데이터 로드](#vacuum-load-in-sort-key-order)
+ [시계열 테이블을 사용하여 저장된 데이터 줄이기](#vacuum-time-series-tables)

## reindex 실행 여부 결정
<a name="r_vacuum-decide-whether-to-reindex"></a>

인터리브 정렬 스타일을 사용하면 종종 쿼리 성능을 크게 높일 수 있지만 정렬 키 열의 값 분산이 변경되면 시간이 지남에 따라 성능이 저하될 수 있습니다.

COPY 또는 CREATE TABLE AS를 사용하여 비어 있는 인터리브 테이블에 처음 로드할 때는 Amazon Redshift가 인터리브 인덱스를 자동으로 구축합니다. INSERT를 사용하여 인터리브 테이블에 처음 로드하는 경우에는 이후 VACUUM REINDEX를 실행하여 인터리브 인덱스를 초기화해야 합니다.

시간이 지나면서 새로운 정렬 키 값이 포함된 행을 추가하여 정렬 키 열의 값 분산이 바뀌면 성능이 떨어질 수 있습니다. 하지만 새로운 행이 기존 정렬 키 값의 범위만 벗어나지 않는다면 인덱스를 다시 빌드할 필요가 없습니다. VACUUM SORT ONLY 또는 VACUUM FULL을 실행하여 정렬 순서를 복원하세요.

쿼리 엔진은 정렬 순서를 사용하여 쿼리 처리를 위해 스캔해야 하는 데이터 블록을 효율적으로 선택할 수 있습니다. 인터리브 정렬의 경우 Amazon Redshift는 정렬 키 열 값을 분석하여 최적의 정렬 순서를 결정합니다. 행이 추가되어 키 값의 분산이 변경되거나 스큐되면 정렬 전략이 더 이상 최적이 아니게 되며, 정렬의 성능상 이득이 저하됩니다. 정렬 키 분산을 다시 분석하기 위해 VACUUM REINDEX를 실행할 수 있습니다. reindex 작업은 시간이 많이 걸리므로 reindex가 테이블에 이득이 될지 결정하려면 [SVV\$1INTERLEAVED\$1COLUMNS](r_SVV_INTERLEAVED_COLUMNS.md) 뷰를 쿼리하세요.

예를 들어 다음 쿼리는 인터리브 정렬 키를 사용하는 테이블의 세부 정보를 보여 줍니다.

```
select tbl as tbl_id, stv_tbl_perm.name as table_name, 
col, interleaved_skew, last_reindex
from svv_interleaved_columns, stv_tbl_perm
where svv_interleaved_columns.tbl = stv_tbl_perm.id
and interleaved_skew is not null;


 tbl_id | table_name | col | interleaved_skew | last_reindex
--------+------------+-----+------------------+--------------------
 100048 | customer   |   0 |             3.65 | 2015-04-22 22:05:45
 100068 | lineorder  |   1 |             2.65 | 2015-04-22 22:05:45
 100072 | part       |   0 |             1.65 | 2015-04-22 22:05:45
 100077 | supplier   |   1 |             1.00 | 2015-04-22 22:05:45
(4 rows)
```

`interleaved_skew`의 값은 스큐의 양을 나타내는 비율입니다. 값이 1이면 적용된 제한이 없는 것입니다. 스큐가 1.4보다 크면 일반적으로 스큐가 기본 집합에 내재하지 않는 한 VACUUM REINDEX로 성능이 개선됩니다.

`last_reindex`의 날짜 값을 사용하면 마지막 reindex 후 얼마나 지났는지 확인할 수 있습니다.

## 정렬되지 않은 리전 크기 줄이기
<a name="r_vacuum_diskspacereqs"></a>

이미 데이터가 포함되어 있는 테이블에 대량의 새 데이터를 로드하거나 일상적 유지 관리 작업의 일환으로 테이블을 vacuum하지 않으면 정렬되지 않은 리전이 늘어납니다. vacuum 작업이 오래 실행되는 것을 방지하려면 다음과 같은 습관을 들이세요.
+ 정기적인 일정에 따라 vacuum 작업을 실행합니다.

  테이블을 조금씩 증분하여 로드하는 경우(테이블의 전체 행 수의 작은 비율에 해당하는 일일 업데이트 등), 정기적으로 VACUUM을 실행하면 개별 vacuum 작업이 빠르게 진행되는 데 도움이 됩니다.
+ 가장 큰 로드를 먼저 실행합니다.

  COPY 작업을 여러 번 사용하여 새 테이블을 로드해야 하는 경우, 가장 큰 로드를 먼저 실행합니다. 새 테이블이나 잘린 테이블에 첫 로드를 실행할 때는 정렬된 리전으로 모든 데이터가 직접 로드되므로 vacuum이 필요하지 않습니다.
+ 모든 행을 삭제하는 대신 테이블을 자릅니다.

  테이블에 행을 삭제해도 vacuum 작업을 수행할 때까지는 행이 차지하던 공간이 회수되지 않습니다. 그러나 테이블을 자르면 테이블이 비워 지고 디스크 공간이 회수되므로 vacuum이 필요하지 않습니다. 또는 테이블을 삭제하고 다시 만드세요.
+ 테스트 테이블을 자르거나 삭제합니다.

  테스트 목적으로 소수의 행을 테이블에 로드하는 경우, 로드가 끝난 후 행을 삭제하지 마세요. 그 대신 테이블을 자르고 후속 프로덕션 로드 작업의 일환으로 이 행들을 다시 로드합니다.
+ 전체 복사를 수행합니다.

  복합 정렬 키를 사용하는 테이블에 정렬되지 않은 큰 리전이 있는 경우, 전체 복사가 vacuum보다 훨씬 빠릅니다. 전체 복사는 대량 삽입을 사용하여 테이블을 다시 생성하고 다시 채움으로써 테이블을 자동으로 다시 정렬합니다. 테이블에 정렬되지 않은 큰 리전이 있는 경우, 전체 복사가 vacuum보다 훨씬 빠릅니다. 반면 전체 복사 작업 중에는 vacuum 중에는 가능한 동시 업데이트를 할 수 없다는 단점이 있습니다. 자세한 내용은 [Amazon Redshift 쿼리 설계 모범 사례](c_designing-queries-best-practices.md) 섹션을 참조하세요.

## 병합된 행의 볼륨 줄이기
<a name="vacuum-managing-volume-of-unmerged-rows"></a>

vacuum 작업이 새 행을 테이블의 정렬된 리전에 병합해야 하는 경우, 테이블이 커질수록 vacuum에 필요한 시간이 늘어납니다. 병합해야 하는 행의 수를 줄이면 vacuum 성능을 높일 수 있습니다.

vacuum 전에 테이블은 테이블 헤드에 있는 정렬된 리전과 그 뒤에 오는, 행이 추가되거나 업데이트될 때마다 증가하는 정렬되지 않은 리전으로 구성됩니다. COPY 작업에 의해 행 세트가 추가되면 새로운 행 세트는 테이블 끝에 있는 정렬되지 않은 리전에 추가될 때 정렬 키에서 정렬됩니다. 새 행들은 자체 세트 안에서는 정렬되어 있지만 정렬되지 않은 리전 안에서는 그렇지 않습니다.

다음 다이어그램은 2회 연속 COPY 작업 후의 정렬되지 않은 리전을 보여 주며, 여기서 정렬 키는 CUSTID입니다. 이 예에는 간단히 하기 위해 복합 정렬 키가 나와 있지만 정렬되지 않은 리전의 효과가 더 크다는 점만 제외하면 인터리브 정렬 키에도 동일한 원리가 적용됩니다.

![\[두 COPY 작업의 레코드를 보관하는 정렬되지 않은 테이블입니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/vacuum-unsorted-region.png)


vacuum은 2단계로 테이블의 정렬 순서를 복원합니다.

1. 정렬되지 않은 리전을 새로 정렬된 리전으로 정렬합니다.

   첫 번째 단계는 비교적 리소스를 적게 사용하는데 정렬되지 않은 리전만 다시 작성되기 때문입니다. 새로 정렬된 리전의 정렬 키 값의 범위가 기존 범위보다 높다면 새 행들만 다시 작성하면 되며, vacuum이 완료됩니다. 예를 들어 정렬된 리전에 ID 값 1\$1500이 포함되어 있고 후속 복사 작업이 500보다 큰 키 값을 추가하는 경우, 정렬되지 않은 리전을 재작성하면 됩니다.

1. 새로 정렬된 리전과 이전에 정렬된 리전을 병합합니다.

   새로 정렬된 리전의 키가 정렬된 리전의 키와 중첩되는 경우, VACUUM은 행을 병합해야 합니다. vacuum은 새로 정렬된 리전의 시작 부분(가장 낮은 정렬 키)에서 시작해 이전에 정렬된 리전과 새로 정렬된 리전의 병합된 행들을 새 블록 세트에 작성합니다.

새 정렬 키 범위와 기존 정렬 키의 중첩 정도는 이전에 정렬된 리전을 어느 정도까지 다시 작성해야 하는지 결정합니다. 정렬되지 않은 키가 기존 정렬 범위 전체에 흩어져 있는 경우, vacuum은 테이블의 기존 부분을 다시 작성해야 할 수 있습니다.

다음 다이어그램은 CUSTID가 정렬 키인 테이블에 추가되는 행들을 vacuum이 어떻게 정렬하고 병합하는지 보여 줍니다. 각각의 복사 작업이 기존 키와 중첩되는 키 값을 가진 새로운 행 세트를 추가하기 때문에 거의 테이블 전체를 다시 작성해야 합니다. 이 다이어그램에는 단일 정렬 및 병합이 나와 있지만 실제로 큰 vacuum은 일련의 증분적 정렬 및 병합 단계로 구성됩니다.

![\[2단계로 구성된 예제 테이블의 VACUUM 작업입니다. 먼저 새 행이 정렬된 다음 기존 행과 병합됩니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/vacuum-unsorted-region-sort-merge.png)


새로운 행 세트의 정렬 키 범위가 기존 키의 범위와 중첩되는 경우, 병합 단계 비용은 테이블이 커지는 데 따라 테이블 크기에 비례하여 계속 증가하는 반면 정렬 단계의 비용은 정렬되지 않은 리전의 크기에 여전히 비례합니다. 이런 경우, 다음 다이어그램에서 보듯 병합 단계의 비용은 정렬 단계의 비용과의 비교가 무색합니다.

![\[새 행에 정렬 키가 기존 행과 중복되면 병합 단계가 어떻게 더 많은 비용이 드는지 보여 주는 다이어그램입니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/vacuum-example-merge-region-grows.png)


테이블 중에서 다시 병합된 비율을 확인하려면 vacuum 작업이 완료된 후 SVV\$1VACUUM\$1SUMMARY를 쿼리합니다. 다음 쿼리는 시간이 흐르면서 CUSTSALES가 계속 커짐에 따른 6회 연속 vacuum의 효과를 보여 줍니다.

```
select * from svv_vacuum_summary
where table_name = 'custsales';


 table_name | xid  | sort_      | merge_     | elapsed_   | row_  | sortedrow_ | block_  | max_merge_
            |      | partitions | increments | time       | delta | delta      | delta   | partitions
 -----------+------+------------+------------+------------+-------+------------+---------+---------------
  custsales | 7072 |          3 |          2 |  143918314 |     0 |   88297472 |   1524  |      47
  custsales | 7122 |          3 |          3 |  164157882 |     0 |   88297472 |    772  |      47
  custsales | 7212 |          3 |          4 |  187433171 |     0 |   88297472 |    767  |      47
  custsales | 7289 |          3 |          4 |  255482945 |     0 |   88297472 |    770  |      47
  custsales | 7420 |          3 |          5 |  316583833 |     0 |   88297472 |    769  |      47
  custsales | 9007 |          3 |          6 |  306685472 |     0 |   88297472 |    772  |      47
 (6 rows)
```

merge\$1increments 열은 각각의 vacuum 작업을 위해 병합된 데이터 양을 표시합니다. 연속적 vacuum 동안 병합 증분의 수가 테이블 크기 증가에 비례하여 증가하는 경우, 이는 기존의 정렬된 리전과 새로 정렬된 리전이 중첩되기 때문에 각각의 vacuum 작업이 다시 병합하는 이 테이블의 행이 증가하고 있다는 뜻입니다.

## 정렬 키 순서로 데이터 로드
<a name="vacuum-load-in-sort-key-order"></a>

COPY 명령을 사용하여 데이터를 정렬 키 순서로 로드하면 vacuum 필요성을 줄이거나 심지어 없앨 수도 있습니다.

다음이 모두 참인 경우, COPY는 새 행을 테이블의 정렬된 리전에 자동으로 추가합니다.
+ 테이블이 하나의 정렬 열에만 복합 정렬 키를 사용합니다.
+ 정렬 열은 NOT NULL입니다.
+ 테이블이 100% 정렬되어 있거나 비어 있습니다.
+ 모든 새 행은 삭제 대기 상태인 행을 포함하여 기존 행보다 정렬 순서가 더 높습니다. 이 인스턴스에서 Amazon Redshift는 정렬 키의 첫 8바이트를 사용하여 정렬 순서를 결정합니다.
+  COPY 명령은 특정 로드 최적화를 트리거하지 않습니다. 대용량 데이터를 로드할 때 Amazon Redshift는 테이블의 정렬된 리전에 행을 추가하는 대신 정렬된 파티션을 새로 생성하여 성능을 최적화할 수 있습니다.

예를 들어 고객 ID와 시간을 사용하여 고객 이벤트를 기록하는 테이블이 있다고 가정해 보세요. 고객 ID에서 정렬하는 경우, 앞의 예에서 보듯 증분적 로드에 의해 추가된 새 행의 정렬 키 범위가 기존 범위와 중첩되어 vacuum 작업이 리소스를 많이 사용하게 됩니다.

정렬 키를 타임스탬프 열로 설정하면 다음 다이어그램에 나온 것처럼 새 행들이 테이블 끝에서 정렬 순서로 추가되어 vacuum 필요성이 줄어들거나 심지어 없어집니다.

![\[타임스탬프 열을 정렬 키로 사용하여 정렬할 필요가 없는 새 레코드를 가져오는 테이블입니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/vacuum-unsorted-region-date-sort.png)


## 시계열 테이블을 사용하여 저장된 데이터 줄이기
<a name="vacuum-time-series-tables"></a>

롤링 기간 동안 데이터를 유지하는 경우, 다음 다이어그램에 나온 것처럼 시계열 테이블을 사용하세요.

![\[5분기의 데이터가 포함된 테이블 5개입니다. 가장 오래된 테이블이 삭제되어 1년의 롤링 시간을 유지합니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/vacuum-example-unsorted-region-copy-time-series.png)


데이터 세트를 추가할 때마다 새 테이블을 만든 다음 시계열에서 가장 오래된 테이블을 삭제합니다. 두 가지 장점이 있습니다.
+ DROP TABLE 작업이 대량 DELETE보다 훨씬 효율적이기 때문에 행 삭제에 따른 비용 추가를 피할 수 있습니다.
+ 테이블이 타임스탬프를 기준으로 정렬되면 vacuum이 필요 없습니다. 각 테이블에 한 달 동안의 데이터가 포함된 경우, 테이블이 타임스탬프를 기준으로 정렬되어 있지 않더라도 vacuum이 다시 써야 하는 데이터 양은 한 달치에 불과합니다.

데이터가 여러 테이블에 저장되어 있다는 사실을 감추는, 보고 쿼리가 사용할 UNION ALL 뷰를 생성할 수 있습니다. 쿼리가 정렬 키에서 필터를 적용하는 경우, 쿼리 플래너는 사용되지 않는 모든 테이블을 효율적으로 건너뜁니다. 다른 유형의 쿼리에는 UNION ALL이 비효율적일 수 있으므로 테이블을 사용하는 모든 쿼리의 컨텍스트에서 쿼리 성능을 평가해야 합니다.

# 동시 쓰기 작업 관리
<a name="c_Concurrent_writes"></a>

일부 애플리케이션은 동시 쿼리 및 로드뿐 아니라 여러 테이블에 또는 같은 테이블 동시에 쓸 수 있는 능력이 필요합니다. 이 맥락에서 *동시에*는 정확히 같은 시간에 실행되도록 예약된 것을 말하는 것이 아니라 중첩된다는 뜻입니다. 첫 번째 트랜잭션이 커밋되기 전에 두 번째 트랜잭션이 시작된다면 두 트랜잭션은 동시적이라고 간주됩니다. 동시 작업은 같은 사용자 또는 서로 다른 사용자에 의해 제어되는 서로 다른 세션에서 비롯될 수 있습니다.

Amazon Redshift는 테이블이 증분적으로 로드되거나 수정되는 동안 테이블을 읽을 수 있도록 함으로써 이런 유형의 애플리케이션을 지원합니다. 쿼리는 다음 버전이 커밋되기를 기다리는 것이 아니라 가장 최근에 커밋된 데이터 버전 또는 *스냅샷*을 단순히 확인합니다. 특정 쿼리가 다른 쓰기 작업으로부터의 커밋을 기다리도록 하려면 그에 따라 일정을 세워야 합니다.

**참고**  
Amazon Redshift는 별도로 실행되는 각각의 SQL 명령이 개별적으로 커밋되는 기본 *자동 커밋* 동작을 지원합니다. 명령 세트를 트랜잭션 블록([BEGIN](r_BEGIN.md) 및 [END](r_END.md) 문에 의해 정의됨)으로 묶는 경우, 이 블록은 하나의 트랜잭션으로 커밋되므로 필요할 경우, 롤백할 수 있습니다. 이 동작에 대한 예외가 TRUNCATE 및 VACUUM 명령으로서 현재 트랜잭션의 대기 중인 모든 변경을 자동으로 커밋합니다.  
일부 SQL 클라이언트는 BEGIN 및 COMMIT 명령을 자동으로 실행하므로 클라이언트는 명령문 그룹이 트랜잭션으로 실행되는지 각 개별 명령문이 자체 트랜잭션으로 실행되는지 여부를 제어합니다. 사용 중인 인터페이스의 설명서를 확인하세요. 예를 들어 Amazon Redshift JDBC 드라이버를 사용할 경우 세미콜론으로 구분된 여러 SQL 명령이 포함된 쿼리 문자열이 있는 JDBC `PreparedStatement`는 모든 명령문을 단일 트랜잭션으로 실행합니다. 반대로 SQL Workbench/J를 사용하고 AUTO COMMIT ON을 설정한 경우 여러 명령문을 실행하면 각 명령문이 자체 트랜잭션으로 실행됩니다.

다음 주제에서는 트랜잭션, 데이터베이스 스냅샷, 업데이트, 동시 동작과 관련하여 몇 가지 주요 개념과 사용 사례를 설명합니다.

**Topics**
+ [Amazon Redshift의 격리 수준](c_serial_isolation.md)
+ [쓰기 및 읽기/쓰기 작업](c_write_readwrite.md)
+ [동시 쓰기 예](r_Serializable_isolation_example.md)
+ [직렬화 가능한 격리 오류 문제 해결](c_serial_isolation-serializable-isolation-troubleshooting.md)

# Amazon Redshift의 격리 수준
<a name="c_serial_isolation"></a>

Amazon Redshift에서 동시 쓰기 작업은 테이블에서의 쓰기 잠금 및 *직렬화 가능 격리* 원칙을 사용하여 보호적 방식으로 지원됩니다. 직렬화 가능 격리는 테이블에 대해 실행 중인 트랜잭션이 해당 테이블에 대해 실행 중인 유일한 트랜잭션이라는 환상을 보존합니다.

Amazon Redshift 데이터베이스는 각 작업이 트랜잭션 시작 시 데이터의 최신 커밋된 버전 또는 스냅샷을 사용하도록 하여 동시 쓰기 작업을 지원합니다. 데이터베이스 스냅샷은 대부분의 SELECT 문과 COPY, DELETE, INSERT, UPDATE, TRUNCATE 같은 DML 명령 및 다음의 DDL 명령이 처음 발생할 때 트랜잭션 내에서 생성됩니다.
+  ALTER TABLE(열 추가 또는 삭제) 
+  CREATE TABLE 
+  DROP TABLE 
+  TRUNCATE TABLE 

다른 트랜잭션은 이 스냅샷을 변경할 수 없습니다. 즉, 트랜잭션이 서로 격리됩니다. 다시 말해 동시 트랜잭션은 서로에게 보이지 않으며, 서로의 변경을 감지할 수 없습니다.

트랜잭션의 모든 동시 실행은 해당 트랜잭션의 직렬 실행과 동일한 결과를 생성해야 합니다. 동일한 결과를 생성할 수 있는 이러한 트랜잭션의 순차 실행이 없는 경우 직렬화 기능을 중단하는 문을 실행하는 트랜잭션은 중지되고 롤백됩니다.

예를 들어 사용자가 T1과 T2라는 두 개의 동시 트랜잭션을 실행하려고 한다고 가정해 보겠습니다. T1 및 T2를 실행하면 다음 시나리오 중 하나 이상과 동일한 결과가 생성되어야 합니다.
+ T1과 T2가 이 순서로 순차 실행됩니다.
+ T2와 T1이 이 순서로 순차 실행됩니다.

 Amazon Redshift의 격리 수준은 다음 문제를 방지합니다.
+  더티 읽기 - 더티 읽기는 트랜잭션이 아직 커밋되지 않은 데이터를 읽을 때 발생합니다. 예를 들어 트랜잭션 1이 행을 업데이트한다고 가정해 보겠습니다. 트랜잭션 2는 T1이 업데이트를 커밋하기 전에 업데이트된 행을 읽습니다. T1이 변경 사항을 롤백하면 T2는 Amazon Redshift에서 이제 존재하지 않은 것으로 간주하는 커밋되지 않은 행의 읽기 데이터를 갖게 됩니다.
+  반복할 수 없는 읽기 - 반복할 수 없는 읽기는 단일 트랜잭션이 동일한 행을 두 번 읽지만 매번 다른 데이터를 가져올 때 발생합니다. 예를 들어 트랜잭션 1이 행을 읽는다고 가정합니다. 트랜잭션 2는 해당 행을 업데이트 또는 삭제하고 업데이트 또는 삭제를 커밋합니다. T1이 행을 다시 읽으면 다른 행 값을 검색하거나 행이 삭제되었음을 발견합니다.
+  팬텀 - 팬텀은 검색 기준과 일치하지만 처음에는 보이지 않는 행입니다. 예를 들어 트랜잭션 1이 검색 기준을 충족하는 행 집합을 읽었다고 가정합니다. 트랜잭션 2는 T1의 검색 기준과 일치하는 UPDATE 또는 INSERT 문에 새 행을 생성합니다. T1이 검색 문을 다시 실행하면 다른 행 집합을 가져옵니다.

## SNAPSHOT 및 SERIALIZABLE 격리
<a name="c_serial_isolation-snapshot_and_serializable"></a>

SERIALIZABLE 및 SNAPSHOT 격리는 직렬화 가능한 두 가지 격리 수준으로, Amazon Redshift에서 사용할 수 있습니다.

SNAPSHOT 격리는 프로비저닝된 클러스터 및 서버리스 작업 그룹을 생성할 때의 기본 격리 수준이므로 SERIALIZABLE 격리보다 더 많은 양의 데이터를 더 짧은 시간 내에 처리할 수 있습니다.

SERIALIZABLE 격리에는 시간이 더 걸리지만 동시 트랜잭션에 대해 더 엄격한 제약 조건을 구현합니다. 이 격리 수준은 직렬화 가능한 격리 위반 오류가 있는 다른 모든 동시 트랜잭션을 취소하는 동시에 하나의 트랜잭션만 커밋하도록 허용하여 쓰기 스큐 이상과 같은 문제를 방지합니다.

다음은 SNAPSHOT 격리를 사용할 때 두 개의 동시 쓰기 작업을 처리하는 방법의 타임라인 예제입니다. 각 사용자의 UPDATE 문은 동일한 행을 업데이트하려고 해도 충돌하지 않으므로 커밋할 수 있습니다.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/c_serial_isolation.html)

직렬화 가능 격리를 사용하여 동일한 시나리오를 실행하는 경우 Amazon Redshift 직렬화 가능 위반으로 인해 사용자 2를 종료하고 오류 `1023`을 반환합니다. 자세한 내용은 [직렬화 가능한 격리 오류 문제 해결](c_serial_isolation-serializable-isolation-troubleshooting.md) 섹션을 참조하세요. 이 경우 사용자 1만 성공적으로 커밋할 수 있습니다.

## 고려 사항
<a name="c_serial_isolation-considerations"></a>

Amazon Redshift에서 격리 수준을 사용할 때는 다음 사항을 고려하세요.
+  STV\$1DB\$1ISOLATION\$1LEVEL 카탈로그 보기를 쿼리하여 데이터베이스에서 사용 중인 격리 수준을 확인합니다. 자세한 내용은 [STV\$1DB\$1ISOLATION\$1LEVEL](r_STV_DB_ISOLATION_LEVEL.md) 섹션을 참조하세요.
+  PG\$1DATABASE\$1INFO 뷰를 쿼리하여 데이터베이스에 지원되는 동시 트랜잭션 수를 확인합니다. 자세한 내용은 [PG\$1DATABASE\$1INFO](r_PG_DATABASE_INFO.md) 섹션을 참조하세요.
+  시스템 카탈로그 테이블(PG)과 기타 Amazon Redshift 시스템 테이블은 트랜잭션에서 잠기지 않습니다. 따라서 DDL 및 TRUNCATE 작업에서 발생하는 데이터베이스 객체의 변경 사항은 동시 트랜잭션에 대한 커밋 시 볼 수 있습니다.

   예를 들어 2개의 동시 트랜잭션 T1과 T2가 시작될 때 데이터베이스에 테이블 A가 존재한다고 가정해 보세요. T2가 PG\$1TABLES 카탈로그 테이블에서 선택하여 테이블 목록을 반환한다고 가정합니다. 그런 다음 T1이 테이블 A를 삭제하고 커밋한 다음 T2가 테이블을 다시 나열합니다. 이제 테이블 A가 더 이상 나열되지 않습니다. T2가 삭제된 테이블을 쿼리하려고 하는 경우 Amazon Redshift는 "관계가 존재하지 않음(relation does not exist)" 오류를 반환합니다. 테이블 목록을 T2에 반환하거나 테이블 A가 존재하는지 확인하는 카탈로그 쿼리에는 사용자 테이블에서 수행되는 작업과 동일한 격리 규칙이 적용되지 않습니다.

   이런 테이블의 업데이트를 위한 트랜잭션은 읽기 커밋된 격리 모드에서 실행됩니다.
+  PG-prefix 카탈로그 테이블은 SNAPSHOT 격리를 지원하지 않습니다.

# 쓰기 및 읽기/쓰기 작업
<a name="c_write_readwrite"></a>

다양한 형식의 명령을 언제 어떻게 실행할지 결정하면 동시 쓰기 및 읽기-쓰기 작업의 특정 동작을 관리할 수 있습니다. 이 논의와 관련된 명령은 다음과 같습니다.
+ COPY 명령 - 로드를 수행(초기 또는 증분적 로드)
+ INSERT 명령 - 하나 이상의 행을 한 번에 추가
+ UPDATE 명령 - 기존 행을 수정
+ DELETE 명령 - 행을 제거 

COPY 및 INSERT 작업은 순수 쓰기 작업입니다. DELETE 및 UPDATE 작업은 읽기/쓰기 작업입니다(행을 삭제하거나 업데이트하려면 먼저 읽어야 함). 동시 쓰기 작업의 결과는 동시에 실행 중인 특정 명령에 따라 달라집니다.

UPDATE 작업과 DELETE 작업은 쓰기를 수행하기 전에 초기 테이블 읽기에 의존하므로 서로 다르게 동작합니다. 동시 트랜잭션은 서로에게 보이지 않으므로 UPDATE와 DELETE 모두 마지막 커밋으로부터 데이터 스냅샷을 읽어야 합니다. 첫 번째 UPDATE 또는 DELETE가 잠금을 풀면 두 번째 UPDATE 또는 DELETE는 작업할 데이터가 잠재적으로 부실한지 여부를 확인해야 합니다. 데이터는 부실해지지 않는데, 첫 번째 트랜잭션이 잠금을 풀 때까지 두 번째 트랜잭션은 데이터의 스냅샷을 가져오지 않기 때문입니다.

## 여러 테이블이 포함된 동시 쓰기 트랜잭션의 잠재적 교착 상황
<a name="c_write_readwrite-potential-deadlock"></a>

트랜잭션에 둘 이상의 테이블의 업데이트가 포함되는 경우, 동시에 실행되는 두 트랜잭션이 같은 테이블 세트에 쓰기를 시도하다 교착될 가능성이 늘 존재합니다. 트랜잭션은 커밋하거나 롤백할 때 테이블 잠금을 한 번에 하나씩 풀지 않고 모든 잠금을 한 번에 풉니다.

예를 들어 트랜잭션 T1과 T2가 대략 같은 시간에 시작된다고 가정해 보세요. T1이 테이블 A에 쓰기를 시작하고 T2가 테이블 B에 쓰기를 시작하면 두 트랜잭션이 충돌 없이 진행될 수 있습니다. 하지만 T1이 테이블 A에 대한 쓰기를 마치고 테이블 B에 대한 쓰기를 시작해야 하는 경우에는 T2가 아직 테이블 B를 잠그고 있기 때문에 계속 진행할 수 없습니다. 비슷하게 T2가 테이블 B에 대한 쓰기를 마치고 테이블 A에 대한 쓰기를 시작해야 하는 경우, T1이 테이블 A를 잠그고 있기 때문에 계속 진행할 수 없습니다. 어느 트랜잭션도 쓰기 작업이 커밋될 때까지 잠금을 풀 수 없으므로 어느 트랜잭션도 진행될 수 없는 것입니다. 이런 종류의 교착을 피하기 위해서는 동시 쓰기 작업을 신중하게 예약해야 합니다. 예를 들어 트랜잭션에서 항상 같은 순서로 테이블을 업데이트해야 하며, 잠금을 지정하는 경우에는 DML 작업을 수행하기 전에 같은 순서로 테이블을 잠가야 합니다.

## 하나의 테이블이 포함된 동시 쓰기 트랜잭션의 잠재적 교착 상황
<a name="c_write_readwrite-potential-deadlock-single"></a>

스냅샷 격리 환경에서는 동일한 테이블에서 동시 쓰기 트랜잭션을 실행할 때 교착 상태가 발생할 수 있습니다. 스냅샷 격리 교착 상태는 동시 INSERT 또는 COPY 문이 잠금을 공유하고 진행 중이며 다른 문은 동일한 테이블에 대한 배타적 잠금이 필요한 작업(UPDATE, DELETE, MERGE 또는 DDL 작업)을 수행해야 할 때 발생합니다.

다음 시나리오를 고려해 보세요.

트랜잭션 1(T1):

```
INSERT/COPY INTO table_A;
```

트랜잭션 2(T2):

```
INSERT/COPY INTO table_A; 
            <UPDATE/DELETE/MERGE/DDL statement> table_A
```

교착 상태는 INSERT 또는 COPY 작업이 있는 여러 트랜잭션이 공유 잠금이 있는 동일한 테이블에서 동시에 실행되고, 이러한 트랜잭션 중 하나가 UPDATE, MERGE, DELETE 또는 DDL 문과 같이 배타적 잠금이 필요한 작업으로 순수 쓰기 작업을 따르는 경우에 발생할 수 있습니다.

이러한 상황에서 교착 상태를 방지하려면 INSERT/COPY 문이 동시에 진행되고 배타적 잠금이 필요한 문이 그 이후에 실행될 수 있도록 배타적 잠금이 필요한 문(UPDATE/MERGE/DELETE/DDL 문)을 다른 트랜잭션으로 분리할 수 있습니다. 또는 동일한 테이블에 INSERT/COPY 문과 MERGE/UPDATE/MERGE 문이 있는 트랜잭션의 경우 애플리케이션에 재시도 로직을 포함하여 잠재적 교착 상태를 해결할 수 있습니다.

# 동시 쓰기 예
<a name="r_Serializable_isolation_example"></a>

다음 유사 코드 예는 동시에 실행되는 트랜잭션이 어떻게 진행되는지 또는 대기하는지 보여 줍니다.

## 직렬화 가능한 격리가 포함된 동시 쓰기 예제
<a name="r_Serializable_isolation_example-serializable"></a>

### 직렬화 가능한 격리가 포함된 같은 테이블에 대한 동시 COPY 작업
<a name="r_Serializable_isolation_example-concurrent-copy-operations-into-the-same-table"></a>

트랜잭션 1은 LISTING 테이블에 행을 복사합니다.

```
begin;
copy listing from ...;
end;
```

트랜잭션 2는 별도의 세션에서 동시에 시작되며, LISTING 테이블에 더 많은 행을 복사하려 시도합니다. 트랜잭션 2는 트랜잭션 1이 LISTING 테이블에서 쓰기 잠금을 풀 때까지 기다려야 하며, 그런 다음에야 진행될 수 있습니다.

```
begin;
[waits]
copy listing from ;
end;
```

트랜잭션 하나 또는 둘 모두에 COPY 명령 대신 INSERT 명령이 포함된 경우, 똑같은 동작이 발생합니다.

### 직렬화 가능한 격리가 포함된 같은 테이블로부터의 동시 DELETE 작업
<a name="r_Serializable_isolation_example-concurrent-delete-operations-from-the-same-table"></a>

트랜잭션 1은 테이블에서 행을 삭제합니다.

```
begin;
delete from listing where ...;
end;
```

트랜잭션 2는 동시에 시작되어 같은 테이블에서 행을 삭제하려 시도합니다. 트랜잭션 2는 트랜잭션 1이 완료되기를 기다렸다가 행 삭제를 시도하므로 성공합니다.

```
begin
[waits]
delete from listing where ;
end;
```

트랜잭션 하나 또는 둘 모두에 DELETE 명령 대신 같은 테이블에 대한 UPDATE 명령이 포함된 경우, 똑같은 동작이 발생합니다.

### 직렬화 가능한 격리가 포함된 읽기 작업과 쓰기 작업이 혼합된 동시 트랜잭션
<a name="r_Serializable_isolation_example-concurrent-transactions"></a>

이 예에서 트랜잭션 1은 USERS 테이블에서 행을 삭제하고 이 테이블을 다시 로드하여 COUNT(\$1) 쿼리를 실행한 다음 ANALYZE하고 마지막으로 커밋합니다.

```
begin;
delete one row from USERS table;
copy ;
select count(*) from users;
analyze ;
end;
```

그러는 동안 트랜잭션 2가 시작됩니다. 이 트랜잭션은 추가적인 행을 USERS 테이블에 복사해 테이블을 분석한 다음 첫 번째 트랜잭션과 동일한 COUNT(\$1) 쿼리를 실행하려 시도합니다.

```
begin;
[waits]
copy users from ...;
select count(*) from users;
analyze;
end;
```

두 번째 트랜잭션은 첫 번째 트랜잭션이 완료될 때까지 기다려야 하므로 성공합니다. 이 트랜잭션의 COUNT 쿼리는 완료한 로드를 기준으로 카운트를 반환합니다.

## 스냅샷 격리를 사용한 동시 쓰기 예제
<a name="r_Serializable_isolation_example-snapshot"></a>

### 스냅샷 격리가 포함된 같은 테이블에 대한 동시 COPY 작업
<a name="r_Serializable_isolation_example-concurrent-copy-operations-into-the-same-table-snapshot"></a>

트랜잭션 1은 LISTING 테이블에 행을 복사합니다.

```
begin;
copy listing from ...;
end;
```

트랜잭션 2는 별도의 세션에서 동시에 시작되며, LISTING 테이블에 더 많은 행을 복사하려 시도합니다. 트랜잭션 2는 두 트랜잭션 중 하나가 대상 테이블 `listing`에 데이터를 써야 할 때까지 동시에 진행될 수 있으며, 이 시점에서 순차적으로 실행됩니다.

```
begin; 
//When the COPY statement from T1 needs to write data to the table, the COPY statement from T2 waits.
copy listing from ...; 
end;
```

트랜잭션 하나 또는 둘 모두에 COPY 명령 대신 INSERT 명령이 포함된 경우, 똑같은 동작이 발생합니다.

### 스냅샷 격리가 포함된 같은 테이블로부터의 동시 DELETE 작업
<a name="r_Serializable_isolation_example-concurrent-delete-operations-from-the-same-table-snapshot"></a>

스냅샷 격리가 있는 동일한 테이블로부터의 동시 DELETE 또는 UPDATE 작업은 직렬화 가능한 격리로 실행되는 작업과 동일하게 실행됩니다.

### 스냅샷 격리가 포함된 읽기 작업과 쓰기 작업이 혼합된 동시 트랜잭션
<a name="r_Serializable_isolation_example-concurrent-transactions-snapshot"></a>

스냅샷 격리가 있는 작업의 혼합으로 실행되는 동시 트랜잭션은 직렬화 가능한 격리로 실행되는 작업의 혼합이 있는 트랜잭션과 동일하게 실행됩니다.

# 직렬화 가능한 격리 오류 문제 해결
<a name="c_serial_isolation-serializable-isolation-troubleshooting"></a>

## ERROR:1023 DETAIL: Redshift의 테이블에서 직렬화 가능한 격리 위반
<a name="c_serial_isolation-serialization-isolation-1023"></a>

Amazon Redshift에서 직렬화 가능 격리 오류를 감지하면 다음과 같은 오류 메시지가 표시됩니다.

```
ERROR:1023 DETAIL: Serializable isolation violation on table in Redshift
```

직렬화 가능 격리 오류를 해결하기 위해 다음과 같은 방법을 시도할 수 있습니다.
+ 취소된 트랜잭션을 재시도합니다.

   Amazon Redshift에서 동시 워크로드를 직렬화할 수 없음을 감지했습니다. 이는 일반적으로 오류가 발생한 트랜잭션을 재시도하여 해결할 수 있는 애플리케이션 논리의 차이를 나타냅니다. 문제가 지속되면 다른 방법 중 하나를 시도하세요.
+ 동일한 원자성 트랜잭션에 있을 필요가 없는 모든 작업을 트랜잭션 외부로 이동합니다.

  이 방법은 두 개의 트랜잭션 내에 있는 개별 작업이 다른 트랜잭션의 결과에 영향을 미칠 수 있는 방식으로 상호 참조하는 경우에 사용할 수 있습니다. 예를 들어 다음 두 세션은 각자 트랜잭션을 시작합니다.

  ```
  Session1_Redshift=# begin;
  ```

  ```
  Session2_Redshift=# begin;
  ```

  각 트랜잭션에 있는 SELECT 문의 결과는 다른 트랜잭션에 있는 INSERT 문에 영향을 받을 수 있습니다. 다시 말해 다음과 같은 문을 어떤 순서로든 직렬 방식으로 실행한다고 가정합시다. 어떤 경우에도 트랜잭션이 동시에 실행된 경우보다 한 행을 더 반환하는 SELECT 문 중 하나를 얻게 됩니다. 작업을 직렬로 실행하여 동시에 실행할 때와 동일한 결과를 산출할 수 있는 순서는 없습니다. 따라서 마지막으로 실행되는 작업으로 인해 직렬화 가능 격리 오류가 발생합니다.

  ```
  Session1_Redshift=# select * from tab1;
  Session1_Redshift=# insert into tab2 values (1);
  ```

  ```
  Session2_Redshift=# insert into tab1 values (1);
  Session2_Redshift=# select * from tab2;
  ```

  많은 경우 SELECT 문의 결과는 중요하지 않습니다. 다시 말해 트랜잭션 내 작업의 원자성은 중요하지 않습니다. 이러한 경우에는 다음 예와 같이 SELECT 문을 트랜잭션 외부로 이동합니다.

  ```
  Session1_Redshift=# begin;
  Session1_Redshift=# insert into tab1 values (1)
  Session1_Redshift=# end;
  Session1_Redshift=# select * from tab2;
  ```

  ```
  Session2_Redshift # select * from tab1;
  Session2_Redshift=# begin;
  Session2_Redshift=# insert into tab2 values (1)
  Session2_Redshift=# end;
  ```

  이 예의 경우 트랜잭션 내 교차 참조는 없습니다. 두 가지 INSERT 문은 서로에게 영향을 미치지 않습니다. 이 예의 경우 트랜잭션이 직렬로 실행되어 동시에 실행될 때와 동일한 결과를 산출하는 순서가 최소 한 개 있습니다. 이는 트랜잭션을 직렬화할 수 있음을 뜻합니다.
+ 각 세션에서 모든 테이블을 잠가 직렬화를 강제 실행하세요.

  [LOCK](r_LOCK.md) 명령은 직렬화 가능 격리 오류를 발생시킬 수 있는 작업을 차단합니다. LOCK 명령 사용 시 다음을 반드시 수행하세요.
  + 트랜잭션 내 읽기 전용 SELECT 문의 영향을 받는 테이블을 포함해 트랜잭션의 영향을 받는 모든 테이블을 잠급니다.
  + 작업이 수행되는 순서에 상관없이 테이블을 동일한 순서로 잠급니다.
  + 작업을 수행하기 전에 트랜잭션을 시작하는 시점에 모든 테이블을 잠급니다.
+ 동시 트랜잭션에는 스냅샷 격리를 사용하세요.

  ALTER DATABASE 명령을 스냅샷 격리와 함께 사용하세요. ALTER DATABASE의 SNAPSHOT 파라미터에 대한 자세한 내용은 [파라미터](r_ALTER_DATABASE.md#r_ALTER_DATABASE-parameters) 섹션을 참조하세요.

## ERROR:1018 DETAIL: 관계가 존재하지 않음
<a name="c_serial_isolation-serialization-isolation-1018"></a>

여러 세션에서 동시 Amazon Redshift 작업을 실행하면 다음과 같은 오류 메시지가 표시됩니다.

```
ERROR: 1018 DETAIL: Relation does not exist.
```

Amazon Redshift의 트랜잭션은 스냅샷 격리를 따릅니다. 트랜잭션이 시작된 후 Amazon Redshift는 데이터베이스의 스냅샷을 만듭니다. 트랜잭션의 전체 수명 주기 동안 트랜잭션은 스냅샷에 반영된 데이터베이스 상태에서 작동합니다. 트랜잭션이 스냅샷에 존재하지 않는 테이블에서 읽는 경우 이전에 표시된 1018 오류 메시지가 나타납니다. 트랜잭션이 스냅샷을 만든 후 다른 동시 트랜잭션이 테이블을 생성하더라도 트랜잭션은 새로 생성된 테이블에서 읽을 수 없습니다.

이 직렬화 격리 오류를 해결하기 위해 테이블이 존재함을 알고 있는 시점으로 트랜잭션 시작을 이동하려고 할 수 있습니다.

테이블이 다른 트랜잭션에 의해 생성된 경우 이 시점은 적어도 해당 트랜잭션이 커밋된 이후입니다. 또한 테이블을 삭제했을 수 있는 동시 트랜잭션이 커밋되지 않았는지 확인합니다.

```
session1 = # BEGIN;
session1 = # DROP TABLE A;
session1 = # COMMIT;
```

```
session2 = # BEGIN;
```

```
session3 = # BEGIN;
session3 = # CREATE TABLE A (id INT);
session3 = # COMMIT;
```

```
session2 = # SELECT * FROM A;
```

session2에 의해 읽기 작업으로 실행되는 마지막 작업이 직렬화 가능한 격리 오류를 발생시킵니다. 이 오류는 session2가 스냅샷을 만들고 테이블이 커밋된 session1에 의해 이미 삭제된 경우 발생합니다. 즉, 동시 session3이 테이블을 생성하더라도 session2는 테이블이 스냅샷에 없기 때문에 테이블을 볼 수 없습니다.

이 오류를 해결하기 위해 다음과 같이 세션을 재정렬할 수 있습니다.

```
session1 = # BEGIN;
session1 = # DROP TABLE A;
session1 = # COMMIT;
```

```
session3 = # BEGIN;
session3 = # CREATE TABLE A (id INT);
session3 = # COMMIT;
```

```
session2 = # BEGIN;
session2 = # SELECT * FROM A;
```

이제 session2가 스냅샷을 만들 때 session3은 이미 커밋되었으며 테이블은 데이터베이스에 있습니다. Session2는 오류 없이 테이블에서 읽을 수 있습니다.

# 튜토리얼: Amazon S3에서 데이터 로드
<a name="tutorial-loading-data"></a>

이 튜토리얼에서는 Amazon S3 버킷에 있는 데이터 파일에서 Amazon Redshift 데이터베이스 테이블로 데이터를 로드하는 프로세스를 처음부터 끝까지 살펴봅니다.

이 자습서에서는 다음을 수행합니다.
+ 쉼표로 구분된 값(CSV) 형식, 문자로 구분된 형식, 고정 너비 형식을 사용하는 데이터 파일을 다운로드합니다.
+ Amazon S3 버킷을 생성한 다음 이 버킷에 데이터 파일을 업로드합니다.
+ Amazon Redshift 클러스터를 시작하고 데이터베이스 테이블을 생성합니다.
+ COPY 명령을 사용하여 Amazon S3의 데이터 파일에서 테이블을 로드합니다.
+ 로드 오류 문제를 해결하고 COPY 명령을 수정하여 오류를 수정합니다.

## 사전 조건
<a name="tutorial-loading-data-prerequisites"></a>

필요한 사전 조건은 다음과 같습니다.
+ Amazon Redshift 클러스터를 시작하고 Amazon S3에 버킷을 생성하기 위한 AWS 계정.
+ Amazon S3에서 테스트 데이터를 로드하기 위한 AWS 자격 증명(IAM 역할). 새로운 IAM 역할이 필요한 경우 [IAM 역할 생성](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html)으로 이동합니다.
+ Amazon Redshift 콘솔 쿼리 편집기와 같은 SQL 클라이언트.

이 자습서는 자습서만으로 학습이 가능하도록 만들어졌습니다. Amazon Redshift 데이터베이스의 설계 및 사용 방법을 더 깊이 이해하려면 이 튜토리얼 외에 다음 튜토리얼을 공부하는 것이 좋습니다.
+ [Amazon Redshift 시작 안내서](https://docs.aws.amazon.com/redshift/latest/gsg/)에서는 Amazon Redshift 클러스터를 생성하고 샘플 데이터를 로드하는 프로세스를 안내합니다.

## 개요
<a name="tutorial-loading-data-overview"></a>

INSERT 명령 또는 COPY 명령을 사용하여 Amazon Redshift 테이블에 데이터를 추가할 수 있습니다. Amazon Redshift 데이터 웨어하우스의 규모와 속도에서는 COPY 명령이 INSERT 명령보다 몇 배 더 빠르고 효율적입니다.

COPY 명령은 Amazon Redshift 대량 병렬 처리(MPP) 아키텍처를 사용하여 여러 데이터 원본에서 병렬로 데이터를 읽고 로드합니다. Amazon S3, Amazon EMR 또는 SSH(Secure Shell) 연결을 통해 액세스 가능한 원격 호스트에 있는 데이터 파일에서 로드할 수 있습니다. 또는 Amazon DynamoDB 테이블에서 직접 로드할 수 있습니다.

이 튜토리얼에서는 COPY 명령을 사용하여 Amazon S3에서 데이터를 로드합니다. 여기 설명된 여러 원리는 다른 데이터 원본에서의 로드에도 적용됩니다.

COPY 명령을 사용하는 방법에 대해 자세히 알아보려면 다음 리소스를 참조하세요.
+ [데이터 로드에 대한 Amazon Redshift 모범 사례](c_loading-data-best-practices.md)
+ [Amazon EMR에서 데이터 로드](loading-data-from-emr.md)
+ [원격 호스트에서 데이터 로드](loading-data-from-remote-hosts.md)
+ [Amazon DynamoDB 테이블에서 데이터 로드](t_Loading-data-from-dynamodb.md)

## 1단계: 클러스터 생성
<a name="tutorial-loading-data-launch-cluster"></a>

사용할 클러스터가 이미 있다면 이 단계를 건너뛰어도 됩니다.

이 자습서에서는 연습용으로 4노드 클러스터를 사용합니다.

**클러스터 생성**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/redshiftv2/](https://console.aws.amazon.com/redshiftv2/)에서 Amazon Redshift 콘솔을 엽니다.

   탐색 메뉴에서 **프로비저닝된 클러스터 대시보드**를 선택합니다.
**중요**  
사용자에게 클러스터 작업을 수행하는 데 필요한 권한이 있는지 확인해야 합니다. 필요한 권한을 부여하는 방법에 대한 자세한 내용은 [Amazon Redshift의 AWS 서비스 액세스 권한 부여](https://docs.aws.amazon.com/redshift/latest/mgmt/authorizing-redshift-service.html)를 참조하세요.

1. 오른쪽 상단에서 클러스터를 생성하려는 AWS 리전을 선택합니다. 본 튜토리얼의 목적에 맞게 [**미국 서부(오레곤)(US West (Oregon))**]를 선택합니다.

1. 탐색 메뉴에서 **클러스터(Clusters)**를 선택한 다음 **클러스터 생성(Create cluster)**을 선택합니다. **클러스터 생성** 페이지가 표시됩니다.

1. **클러스터 생성(Create cluster)** 페이지에서 클러스터의 파라미터를 입력합니다. 다음 값을 변경하는 것을 제외하고 파라미터에 대해 고유한 값을 선택합니다.
   + 노드 유형으로 **dc2.large**를 선택합니다.
   + **노드 수(Number of nodes)**로 **4**를 선택합니다.
   + **Cluster permissions(클러스터 권한)** 섹션의 **Available IAM roles(사용 가능한 IAM 역할)**에서 IAM 역할을 선택합니다. 이 역할은 이전에 생성하고 Amazon S3에 액세스할 수 있는 역할이어야 합니다. 그런 다음 **IAM 역할 연결(Associate IAM role)**을 선택하여 클러스터에 대한 **연결된 IAM 역할(Associated IAM roles)** 목록에 추가합니다.

1. **클러스터 생성**을 선택합니다.

[Amazon Redshift 시작 안내서](https://docs.aws.amazon.com/redshift/latest/gsg/) 단계에 따라 SQL 클라이언트에서 클러스터에 연결한 후 연결을 테스트합니다. 그 밖에 테이블을 생성하거나 데이터를 업로드하거나 예제 쿼리를 실행하는 나머지 시작하기 단계는 완료할 필요가 없습니다.

## 2단계: 데이터 파일 다운로드
<a name="tutorial-loading-data-download-files"></a>

이 단계에서는 샘플 데이터 파일 세트를 컴퓨터에 다운로드합니다. 다음 단계에서는 파일을 Amazon S3 버킷에 업로드합니다.

**데이터 파일을 다운로드하려면**

1. 압축된 파일 [LoadingDataSampleFiles.zip](samples/LoadingDataSampleFiles.zip)을 다운로드합니다.

1. 파일을 컴퓨터의 폴더에 압축 해제합니다.

1. 폴더에 다음 파일이 포함되어 있는지 확인합니다.

   ```
   customer-fw-manifest
   customer-fw.tbl-000
   customer-fw.tbl-000.bak
   customer-fw.tbl-001
   customer-fw.tbl-002
   customer-fw.tbl-003
   customer-fw.tbl-004
   customer-fw.tbl-005
   customer-fw.tbl-006
   customer-fw.tbl-007
   customer-fw.tbl.log
   dwdate-tab.tbl-000
   dwdate-tab.tbl-001
   dwdate-tab.tbl-002
   dwdate-tab.tbl-003
   dwdate-tab.tbl-004
   dwdate-tab.tbl-005
   dwdate-tab.tbl-006
   dwdate-tab.tbl-007
   part-csv.tbl-000
   part-csv.tbl-001
   part-csv.tbl-002
   part-csv.tbl-003
   part-csv.tbl-004
   part-csv.tbl-005
   part-csv.tbl-006
   part-csv.tbl-007
   ```

## 3단계: Amazon S3 버킷에 파일 업로드
<a name="tutorial-loading-data-upload-files"></a>

이 단계에서는 Amazon S3 버킷을 생성하고 이 버킷에 데이터 파일을 업로드합니다.

### 
<a name="tutorial-loading-data-to-upload-files"></a>

**Amazon S3 버킷에 파일을 업로드하려면**

1. Amazon S3에서 버킷을 생성합니다.

   버킷 생성에 대한 자세한 내용을 알아보려면 *Amazon Simple Storage Service 사용 설명서*의 [버킷 생성](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)을 참조하세요.

   1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)에서 Amazon S3 콘솔을 엽니다.

   1. **버킷 생성**을 선택합니다.

   1. 을 선택합니다AWS 리전 

      클러스터와 같은 리전에 버킷을 생성합니다. 클러스터가 미국 서부(오레곤) 리전에 있는 경우 **미국 서부(오레곤) 리전(us-west-2)(US West (Oregon) Region (us-west-2))**을 선택합니다.

   1. **버킷 생성** 대화 상자의 **버킷 이름** 상자에 버킷 이름을 입력합니다.

      선택한 버킷 이름은 Amazon S3의 모든 기존 버킷 이름을 통틀어 고유해야 합니다. 고유성을 보장하기 위한 한 가지 방법은 버킷 이름의 접두사로 조직 이름을 사용하는 것입니다. 버킷 이름은 특정 규칙을 준수해야 합니다. 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [버킷 규제 및 제한](https://docs.aws.amazon.com/AmazonS3/latest/userguide/BucketRestrictions.html)을 참조하세요.

   1. 나머지 옵션의 경우 권장 기본값을 선택합니다.

   1. **버킷 생성**을 선택합니다.

      Amazon S3에서 버킷을 생성하면 콘솔의 [**버킷(Buckets)**] 패널에 빈 버킷이 표시됩니다.

1. 폴더를 만듭니다.

   1. 새 버킷의 이름을 선택합니다.

   1. **폴더 생성** 버튼을 선택합니다.

   1. 새 폴더의 이름을 **load**로 지정합니다.
**참고**  
만든 버킷이 샌드박스에 없습니다. 이 연습에서는 실제 버킷에 객체를 추가합니다. 버킷에 객체를 저장한 시간에 대해 명목 금액이 청구됩니다. Amazon S3 요금에 대한 자세한 내용은 [Amazon S3 요금](https://aws.amazon.com/s3/pricing/) 섹션을 참조하세요.

1. 새 Amazon S3 버킷에 데이터 파일을 업로드합니다.

   1. 데이터 폴더의 이름을 선택합니다.

   1. 업로드 마법사에서 **파일 추가**를 선택합니다.

      Amazon S3 콘솔 지침에 따라 다운로드하고 추출한 모든 파일을 업로드합니다.

   1. **업로드**를 선택합니다.
<a name="tutorial-loading-user-credentials"></a>
**사용자 자격 증명**  
Amazon Redshift COPY 명령에 Amazon S3 버킷의 파일 객체를 읽을 수 있는 액세스 권한이 있어야 합니다. Amazon S3 버킷 생성에 사용한 사용자 자격 증명이 Amazon Redshift COPY 명령 실행에 사용하는 자격 증명과 같다면 COPY 명령은 필요한 모든 권한을 가지게 됩니다. 다른 사용자 자격 증명을 사용하려는 경우 Amazon S3 액세스 제어를 사용하여 액세스 권한을 부여하면 됩니다. Amazon Redshift COPY 명령이 Amazon S3 버킷의 파일 객체에 액세스하기 위해서는 적어도 ListBucket 및 GetObject 권한이 필요합니다. Amazon S3 리소스 액세스에 대한 자세한 내용은 [Amazon S3 리소스에 대한 액세스 권한 관리](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html) 섹션을 참조하세요.

## 4단계: 샘플 테이블 생성
<a name="tutorial-loading-data-create-tables"></a>

이 자습서에서는 Star Schema Benchmark(SSB) 스키마에 따라 테이블 세트를 사용합니다. 다음 다이어그램은 SSB 데이터 모델을 나타냅니다.

![\[SSB 스키마의 5개 테이블과 테이블 간의 연관성입니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/tutorial-optimize-tables-ssb-data-model.png)


SSB 테이블이 현재 데이터베이스에 이미 존재할 수 있습니다. 이 경우 데이터베이스에서 이 테이블을 삭제한 후 다음 단계에서 CREATE TABLE 명령을 사용해 테이블을 만들어야 합니다. 이 자습서에서 사용하는 테이블은 기존 테이블과 속성이 다를 수 있습니다.

**샘플 테이블을 만들려면**

1. SSB 테이블을 삭제하려면 SQL 클라이언트에서 다음 명령을 실행합니다.

   ```
   drop table part cascade;
   drop table supplier;
   drop table customer;
   drop table dwdate;
   drop table lineorder;
   ```

1. SQL 클라이언트에서 다음 CREATE TABLE 명령을 실행합니다.

   ```
   CREATE TABLE part 
   (
     p_partkey     INTEGER NOT NULL,
     p_name        VARCHAR(22) NOT NULL,
     p_mfgr        VARCHAR(6),
     p_category    VARCHAR(7) NOT NULL,
     p_brand1      VARCHAR(9) NOT NULL,
     p_color       VARCHAR(11) NOT NULL,
     p_type        VARCHAR(25) NOT NULL,
     p_size        INTEGER NOT NULL,
     p_container   VARCHAR(10) NOT NULL
   );
   
   CREATE TABLE supplier 
   (
     s_suppkey   INTEGER NOT NULL,
     s_name      VARCHAR(25) NOT NULL,
     s_address   VARCHAR(25) NOT NULL,
     s_city      VARCHAR(10) NOT NULL,
     s_nation    VARCHAR(15) NOT NULL,
     s_region    VARCHAR(12) NOT NULL,
     s_phone     VARCHAR(15) NOT NULL
   );
   
   CREATE TABLE customer 
   (
     c_custkey      INTEGER NOT NULL,
     c_name         VARCHAR(25) NOT NULL,
     c_address      VARCHAR(25) NOT NULL,
     c_city         VARCHAR(10) NOT NULL,
     c_nation       VARCHAR(15) NOT NULL,
     c_region       VARCHAR(12) NOT NULL,
     c_phone        VARCHAR(15) NOT NULL,
     c_mktsegment   VARCHAR(10) NOT NULL
   );
   
   CREATE TABLE dwdate 
   (
     d_datekey            INTEGER NOT NULL,
     d_date               VARCHAR(19) NOT NULL,
     d_dayofweek          VARCHAR(10) NOT NULL,
     d_month              VARCHAR(10) NOT NULL,
     d_year               INTEGER NOT NULL,
     d_yearmonthnum       INTEGER NOT NULL,
     d_yearmonth          VARCHAR(8) NOT NULL,
     d_daynuminweek       INTEGER NOT NULL,
     d_daynuminmonth      INTEGER NOT NULL,
     d_daynuminyear       INTEGER NOT NULL,
     d_monthnuminyear     INTEGER NOT NULL,
     d_weeknuminyear      INTEGER NOT NULL,
     d_sellingseason      VARCHAR(13) NOT NULL,
     d_lastdayinweekfl    VARCHAR(1) NOT NULL,
     d_lastdayinmonthfl   VARCHAR(1) NOT NULL,
     d_holidayfl          VARCHAR(1) NOT NULL,
     d_weekdayfl          VARCHAR(1) NOT NULL
   );
   CREATE TABLE lineorder 
   (
     lo_orderkey          INTEGER NOT NULL,
     lo_linenumber        INTEGER NOT NULL,
     lo_custkey           INTEGER NOT NULL,
     lo_partkey           INTEGER NOT NULL,
     lo_suppkey           INTEGER NOT NULL,
     lo_orderdate         INTEGER NOT NULL,
     lo_orderpriority     VARCHAR(15) NOT NULL,
     lo_shippriority      VARCHAR(1) NOT NULL,
     lo_quantity          INTEGER NOT NULL,
     lo_extendedprice     INTEGER NOT NULL,
     lo_ordertotalprice   INTEGER NOT NULL,
     lo_discount          INTEGER NOT NULL,
     lo_revenue           INTEGER NOT NULL,
     lo_supplycost        INTEGER NOT NULL,
     lo_tax               INTEGER NOT NULL,
     lo_commitdate        INTEGER NOT NULL,
     lo_shipmode          VARCHAR(10) NOT NULL
   );
   ```

## 5단계: COPY 명령 실행
<a name="tutorial-loading-run-copy"></a>

COPY 명령을 실행하여 SSB 스키마에서 각각의 테이블을 로드합니다. COPY 명령 예에서는 다양한 파일 형식에서 로드하는 방법, 몇 가지 COPY 명령 옵션을 사용하는 방법, 로드 오류 문제를 해결하는 방법을 보여 줍니다.

### COPY 명령 구문
<a name="tutorial-loading-data-copy-syntax"></a>

기본적인 [COPY](r_COPY.md) 명령 구문은 다음과 같습니다.

```
COPY table_name [ column_list ] FROM data_source CREDENTIALS access_credentials [options] 
```

COPY 명령을 실행하기 위해서는 다음 값을 제공해야 합니다.
<a name="tutorial-loading-syntax-table-name"></a>
**테이블 이름**  
COPY 명령의 대상 테이블. 이 테이블은 사전에 데이터베이스에 존재해야 하며, 임시 테이블일 수도 있고, 영구 테이블일 수도 있습니다. COPY 명령은 새로운 입력 데이터를 테이블의 기존 행에 추가합니다.
<a name="tutorial-loading-syntax-column-list"></a>
**열 목록**  
기본적으로 COPY는 원본 데이터에서 테이블 열로 필드를 순서대로 로드합니다. 필요할 경우, 열 이름이 쉼표로 분리된 *열 목록*을 지정하여 데이터 필드를 특정 열에 매핑할 수 있습니다. 이 자습서에서는 열 목록을 사용하지 않습니다. 자세한 내용은 COPY 명령 참조의 [Column List](copy-parameters-column-mapping.md#copy-column-list) 섹션을 참조하세요.

<a name="tutorial-loading-syntax-data-source.title"></a>데이터 소스: 

COPY 명령을 사용하여 Amazon S3 버킷, Amazon EMR 클러스터, SSH 연결을 사용하는 원격 호스트 또는 Amazon DynamoDB 테이블에서 데이터를 로드할 수 있습니다. 이 튜토리얼에서는 Amazon S3 버킷의 데이터 파일에서 데이터를 로드합니다. Amazon S3에서 로드할 때 버킷 이름과 데이터 파일 위치를 제공해야 합니다. 이렇게 하려면 데이터 파일의 객체 경로 또는 각 데이터 파일과 해당 위치를 명시적으로 나열하는 매니페스트 파일의 위치를 제공합니다.
+ 키 접두사 

  Amazon S3에 저장된 객체는 버킷 이름, 폴더 이름(있는 경우), 객체 이름이 포함된 객체 키에 의해 고유하게 식별됩니다. *키 접두사*는 접두사가 동일한 객체 집합을 말합니다. 객체 경로는 키 접두사로서 해당 키 접두사를 공유하는 모든 객체를 로드할 때 COPY 명령이 사용합니다. 예를 들어 키 접두사 `custdata.txt`는 단일 파일 또는 `custdata.txt.001`, `custdata.txt.002` 등등의 파일 집합을 가리킬 수 있습니다.
+ 매니페스트 파일

  경우에 따라 여러 버킷 또는 폴더와 같이 접두사가 다른 파일을 로드해야 할 수도 있습니다. 또는 접두사를 공유하는 파일을 제외해야 할 수도 있습니다. 이 경우 매니페스트 파일을 사용할 수 있습니다. *매니페스트 파일*은 각각의 로드 파일과 그 고유한 객체 키를 명시적으로 나열합니다. 이 자습서 뒷부분에서는 매니페스트 파일을 사용하여 PART 테이블을 로드합니다.
<a name="tutorial-loading-syntax-credentials"></a>
**자격 증명**  
로드할 데이터가 포함된 AWS 리소스에 액세스하려면 충분한 권한이 있는 사용자의 AWS 액세스 보안 인증 정보를 제공해야 합니다. 이러한 자격 증명에는 IAM 역할 Amazon 리소스 이름(ARN)이 포함됩니다. Amazon S3에서 데이터를 로드하려면 자격 증명에 ListBucket 및 GetObject 권한이 있어야 합니다. 데이터가 암호화된 경우 추가 자격 증명이 필요합니다. 자세한 내용은 COPY 명령 참조의 [권한 부여 파라미터](copy-parameters-authorization.md) 섹션을 참조하세요. 액세스 관리에 대한 자세한 내용은 [Amazon S3 리소스에 대한 액세스 권한 관리](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html) 섹션을 참조하세요.

<a name="tutorial-loading-syntax-options.title"></a>옵션

COPY 명령에 여러 파라미터를 지정하면 파일 형식을 지정하고, 데이터 형식을 관리하고, 오류를 관리하고, 다른 기능을 제어할 수 있습니다. 이 자습서에서 사용하는 COPY 명령 옵션과 기능은 다음과 같습니다.
+ 키 접두사

  키 접두사를 지정하여 여러 파일에서 로드하는 방법에 대한 자세한 내용은 [NULL AS를 사용하여 PART 테이블 로드](#tutorial-loading-load-part) 섹션을 참조하세요.
+ CSV 형식

  CSV 형식의 데이터를 로드하는 방법에 대한 자세한 내용은 [NULL AS를 사용하여 PART 테이블 로드](#tutorial-loading-load-part) 섹션을 참조하세요.
+ NULL AS

  NULL AS 옵션을 사용하여 PART를 로드하는 방법에 대한 자세한 내용은 [NULL AS를 사용하여 PART 테이블 로드](#tutorial-loading-load-part) 섹션을 참조하세요.
+ 문자로 구분된 형식

  DELIMITER 옵션을 사용하는 방법에 대한 자세한 내용은 [DELIMITER 및 REGION 옵션](#tutorial-loading-load-supplier) 섹션을 참조하세요.
+ REGION

  REGION 옵션을 사용하는 방법에 대한 자세한 내용은 [DELIMITER 및 REGION 옵션](#tutorial-loading-load-supplier) 섹션을 참조하세요.
+ 고정 형식 너비

  고정 너비 데이터에서 CUSTOMER 테이블을 로드하는 방법에 대한 자세한 내용은 [MANIFEST를 사용하여 CUSTOMER 테이블 로드](#tutorial-loading-load-customer) 섹션을 참조하세요.
+ MAXERROR

  MAXERROR 옵션을 사용하는 방법에 대한 자세한 내용은 [MANIFEST를 사용하여 CUSTOMER 테이블 로드](#tutorial-loading-load-customer) 섹션을 참조하세요.
+ ACCEPTINVCHARS

  ACCEPTINVCHARS 옵션을 사용하는 방법에 대한 자세한 내용은 [MANIFEST를 사용하여 CUSTOMER 테이블 로드](#tutorial-loading-load-customer) 섹션을 참조하세요.
+ MANIFEST

  MANIFEST 옵션을 사용하는 방법에 대한 자세한 내용은 [MANIFEST를 사용하여 CUSTOMER 테이블 로드](#tutorial-loading-load-customer) 섹션을 참조하세요.
+ DATEFORMAT

  DATEFORMAT 옵션을 사용하는 방법에 대한 자세한 내용은 [DATEFORMAT을 사용하여 DWDATE 테이블 로드](#tutorial-loading-load-dwdate) 섹션을 참조하세요.
+ GZIP, LZOP 및 BZIP2

  파일 압축 방법에 대한 자세한 내용은 [여러 데이터 파일 로드](#tutorial-loading-load-lineorder) 섹션을 참조하세요.
+ COMPUPDATE

  COMPUPDATE 옵션을 사용하는 방법에 대한 자세한 내용은 [여러 데이터 파일 로드](#tutorial-loading-load-lineorder) 섹션을 참조하세요.
+ 여러 파일

  여러 파일을 로드하는 방법에 대한 자세한 내용은 [여러 데이터 파일 로드](#tutorial-loading-load-lineorder) 섹션을 참조하세요.

### SSB 테이블 로드
<a name="tutorial-loading-run-copy-load-tables"></a>

다음 COPY 명령을 사용하여 SSB 스키마에서 각각의 테이블을 로드합니다. 각 테이블에 대한 명령은 다양한 COPY 옵션과 문제 해결 방법을 보여 줍니다.

SSB 테이블을 로드하려면 다음 단계를 따릅니다.

1. [버킷 이름 및 AWS 자격 증명 대체](#tutorial-loading-run-copy-replaceables)

1. [NULL AS를 사용하여 PART 테이블 로드](#tutorial-loading-load-part)

1. [MANIFEST를 사용하여 CUSTOMER 테이블 로드](#tutorial-loading-load-customer)

1. [DATEFORMAT을 사용하여 DWDATE 테이블 로드](#tutorial-loading-load-dwdate)

#### 버킷 이름 및 AWS 자격 증명 대체
<a name="tutorial-loading-run-copy-replaceables"></a>

이 자습서의 COPY 명령은 다음 형식으로 제시되어 있습니다.

```
copy table from 's3://<your-bucket-name>/load/key_prefix' 
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
options;
```

각 COPY 명령에 대해 다음을 수행합니다.

1. *<your-bucket-name>*을 클러스터와 같은 리전에 있는 버킷 이름으로 대체합니다.

   이 단계에서는 버킷과 클러스터가 같은 리전에 있다고 가정합니다. 또는 COPY 명령과 함께 [REGION](copy-parameters-data-source-s3.md#copy-region) 옵션을 사용하여 리전을 지정할 수 있습니다.

1. *<aws-account-id>*와 *<role-name>*을 사용자의 AWS 계정와 IAM 역할로 바꿉니다. 자격 증명 문자열에서 작은따옴표로 묶이는 구간에는 공백이나 줄 바꿈이 있어서는 안 됩니다. ARN은 샘플과 형식이 약간 다를 수 있습니다. COPY 명령을 실행할 때 정확한지 확인하려면 IAM 콘솔에서 역할에 대한 ARN을 복사하는 것이 가장 좋습니다.

#### NULL AS를 사용하여 PART 테이블 로드
<a name="tutorial-loading-load-part"></a>

이 단계에서는 CSV 및 NULL AS 옵션을 사용하여 PART 테이블을 로드합니다.

COPY 명령은 여러 파일에서 데이터를 병렬로 로드할 수 있으므로 단일 파일에서 로드하는 것보다 훨씬 빠릅니다. 이 원리를 보여 주기 위해 이 자습서에서는 각 테이블의 데이터를 아주 작은 여덟 개의 파일로 분할합니다. 이후 단계에서는 단일 파일에서 로드할 때와 여러 파일에서 로드할 때의 시간 차이를 비교합니다. 자세한 내용은 [파일에서 데이터 로드](c_best-practices-use-multiple-files.md) 섹션을 참조하세요.
<a name="tutorial-loading-key-prefix"></a>
**키 접두사**  
파일 세트의 키 접두사를 지정하거나 매니페스트 파일에서 파일을 명시적으로 나열하여 여러 파일에서 데이터를 로드할 수 있습니다. 이 단계에서는 키 접두사를 사용합니다. 매니페스트 파일은 이후 단계에서 사용합니다. 키 접두사 `'s3://amzn-s3-demo-bucket/load/part-csv.tbl'`는 `load` 폴더에 있는 다음 파일 세트를 로드합니다.

```
part-csv.tbl-000
part-csv.tbl-001
part-csv.tbl-002
part-csv.tbl-003
part-csv.tbl-004
part-csv.tbl-005
part-csv.tbl-006
part-csv.tbl-007
```
<a name="tutorial-loading-csv-format"></a>
**CSV 형식**  
쉼표로 분리된 값(comma separated value)을 뜻하는 CSV는 스프레드시트 데이터 가져오기 및 내보내기에 사용되는 공통 형식입니다. CSV는 쉼표로 구분된(comma-delimited) 형식보다 더 유연한데, 필드 내에서 따옴표로 묶인 문자열을 포함시킬 수 있기 때문입니다. CSV 형식에서 COPY의 기본 인용 부호는 큰따옴표(")이지만 QUOTE AS 옵션을 사용하면 다른 인용 부호를 지정할 수 있습니다. 필드 안에서 인용 부호를 사용할 때는 추가 인용 부호로 이스케이프 처리해야 합니다.

PART 테이블용 CSV 형식 데이터 파일에서 발췌한 다음 예는 큰따옴표로 묶인 문자열(`"LARGE ANODIZED BRASS"`)을 보여줍니다. 또한 따옴표로 묶인 문자열 안에서 2개의 큰따옴표로 묶인 문자열(`"MEDIUM ""BURNISHED"" TIN"`)도 보여줍니다.

```
15,dark sky,MFGR#3,MFGR#47,MFGR#3438,indigo,"LARGE ANODIZED BRASS",45,LG CASE
22,floral beige,MFGR#4,MFGR#44,MFGR#4421,medium,"PROMO, POLISHED BRASS",19,LG DRUM
23,bisque slate,MFGR#4,MFGR#41,MFGR#4137,firebrick,"MEDIUM ""BURNISHED"" TIN",42,JUMBO JAR
```

PART 테이블용 데이터에는 COPY가 실패하도록 하는 문자가 포함되어 있습니다. 이 연습에서는 오류 문제를 해결하고 수정합니다.

CSV 형식인 데이터를 로드하려면 COPY 명령에 `csv`를 추가합니다. 다음 명령을 실행하여 PART 테이블을 로드합니다.

```
copy part from 's3://<your-bucket-name>/load/part-csv.tbl' 
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
csv;
```

다음과 비슷한 오류 메시지가 나타날 수 있습니다.

```
An error occurred when executing the SQL command:
copy part from 's3://amzn-s3-demo-bucket/load/part-csv.tbl' 
credentials' ...

ERROR: Load into table 'part' failed.  Check 'stl_load_errors' system table for details. [SQL State=XX000] 

Execution time: 1.46s

1 statement(s) failed.
1 statement(s) failed.
```

오류에 대한 자세한 내용을 보려면 STL\$1LOAD\$1ERRORS 테이블을 쿼리하세요. 다음 쿼리는 SUBSTRING 함수를 사용해 읽기 쉽게 열을 줄이고 LIMIT 10을 사용해 반환되는 행의 수를 줄입니다. 버킷 이름의 길이를 감안하여 `substring(filename,22,25)`에서 값을 조정할 수 있습니다.

```
select query, substring(filename,22,25) as filename,line_number as line, 
substring(colname,0,12) as column, type, position as pos, substring(raw_line,0,30) as line_text,
substring(raw_field_value,0,15) as field_text, 
substring(err_reason,0,45) as reason
from stl_load_errors 
order by query desc
limit 10;
```

```
 query  |    filename      | line |  column   |    type    | pos |      
--------+-------------------------+-----------+------------+------------+-----+----
 333765 | part-csv.tbl-000 |    1 |           |            |   0 |

 line_text        | field_text |                    reason
------------------+------------+----------------------------------------------
 15,NUL next,     |            | Missing newline: Unexpected character 0x2c f
```
<a name="tutorial-loading-null-as"></a>
**NULL AS**  
`part-csv.tbl` 데이터 파일은 NUL 종결자 문자(`\x000` 또는 `\x0`)를 사용하여 NULL 값을 표시합니다.

**참고**  
철자가 매우 비슷함에도 불구하고 NUL과 NULL은 서로 다릅니다. NUL은 레코드 끝(EOR)을 표시하는 데 종종 사용되는 코드포인트 `x000`이 포함된 UTF-8 문자입니다. NULL은 데이터 없음을 나타내는 SQL 값입니다.

기본적으로 COPY는 NUL 종결자 문자를 EOR 문자로 취급하고 레코드를 종결하므로 종종 예상치 못한 오류가 발생합니다. 텍스트 데이터에서 NULL을 나타내는 단일 표준 방법은 없습니다. 그러므로 테이블을 로드할 때 NULL AS COPY 명령 옵션을 사용하여 NULL로 대체할 문자를 지정할 수 있습니다. 이 예에서는 COPY가 NUL 종결자 문자를 NULL 문자로 취급하도록 합니다.

**참고**  
NULL 값을 받는 테이블 열은 *null을 허용하는 열*로 구성되어야 합니다. 다시 말해 CREATE TABLE 사양에서 NOT NULL 제약을 포함해서는 안 됩니다.

NULL AS 옵션을 사용하여 PART를 로드하려면 다음 COPY 명령을 실행합니다.

```
copy part from 's3://<your-bucket-name>/load/part-csv.tbl' 
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
csv
null as '\000';
```

COPY가 NULL 값을 로드했는지 확인하려면 다음 명령을 사용하여 NULL이 포함된 행만 선택합니다.

```
select p_partkey, p_name, p_mfgr, p_category from part where p_mfgr is null;
```

```
 p_partkey |  p_name  | p_mfgr | p_category
-----------+----------+--------+------------
        15 | NUL next |        | MFGR#47
        81 | NUL next |        | MFGR#23
       133 | NUL next |        | MFGR#44 
(2 rows)
```

#### DELIMITER 및 REGION 옵션
<a name="tutorial-loading-load-supplier"></a>

DELIMITER 및 REGION 옵션은 데이터를 로드하는 방법을 이해하는 데 중요합니다.
<a name="tutorial-loading-character-delimited-format"></a>
**문자로 구분된 형식**  
문자로 구분된 파일의 필드는 파이프 문자( \$1 ), 쉼표( , ) 또는 탭( \$1t ) 같은 특정 문자로 분리되어 있습니다. 문자로 구분된 파일은 비인쇄 ASCII 문자 중 하나를 포함한 어떤 단일 ASCII 문자도 구분 기호로 사용할 수 있습니다. DELIMITER 옵션을 사용하여 구분 기호 문자를 지정합니다. 기본 구분자는 파이프 문자(\$1)입니다.

SUPPLIER 테이블용 데이터에서 발췌한 다음 예는 파이프로 구분된 형식을 사용합니다.

```
1|1|257368|465569|41365|19950218|2-HIGH|0|17|2608718|9783671|4|2504369|92072|2|19950331|TRUCK
1|2|257368|201928|8146|19950218|2-HIGH|0|36|6587676|9783671|9|5994785|109794|6|19950416|MAIL
```
<a name="tutorial-loading-region"></a>
**REGION**  
가능하다면 항상 Amazon Redshift 클러스터와 동일한 AWS 리전에 로드 데이터를 위치시켜야 합니다. 데이터와 클러스터가 같은 리전에 있으면 대기 시간이 줄어들고 리전 간 데이터 전송 비용을 피할 수 있습니다. 자세한 내용은 [데이터 로드에 대한 Amazon Redshift 모범 사례](c_loading-data-best-practices.md) 섹션을 참조하세요.

다른 AWS 리전에서 데이터를 로드해야 하는 경우 REGION 옵션을 사용하여 로드 데이터가 위치한 AWS 리전을 지정합니다. 리전을 지정하는 경우, 매니페스트 파일을 포함한 모든 로드 데이터가 명명된 리전에 있어야 합니다. 자세한 내용은 [REGION](copy-parameters-data-source-s3.md#copy-region) 섹션을 참조하세요.

예를 들어 클러스터가 미국 동부(버지니아 북부) 리전에 있고 Amazon S3 버킷이 미국 서부(오리건) 리전에 있는 경우, 다음 COPY 명령은 파이프로 구분된 데이터에서 SUPPLIER 테이블을 로드하는 방법을 보여줍니다.

```
copy supplier from 's3://amzn-s3-demo-bucket/ssb/supplier.tbl' 
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
delimiter '|' 
gzip
region 'us-west-2';
```

#### MANIFEST를 사용하여 CUSTOMER 테이블 로드
<a name="tutorial-loading-load-customer"></a>

이 단계에서는 FIXEDWIDTH, MAXERROR, ACCEPTINVCHARS 및 MANIFEST 옵션을 사용하여 CUSTOMER 테이블을 로드합니다.

이 연습의 샘플 데이터에는 COPY가 로드를 시도할 때 실패를 초래하는 문자가 포함되어 있습니다. MAXERRORS 옵션과 STL\$1LOAD\$1ERRORS 시스템 테이블을 사용하여 로드 오류 문제를 해결한 다음 ACCEPTINVCHARS 및 MANIFEST 옵션을 사용하여 오류를 제거합니다.
<a name="tutorial-loading-fixed-width"></a>
**고정 너비 형식**  
고정 너비 형식은 구분 기호로 필드를 분리하지 않고 각 필드를 고정된 수의 문자로 정의합니다. CUSTOMER 테이블용 데이터에서 발췌한 다음 예는 고정 너비 형식을 사용합니다.

```
1   Customer#000000001   IVhzIApeRb           MOROCCO  0MOROCCO  AFRICA      25-705 
2   Customer#000000002   XSTf4,NCwDVaWNe6tE   JORDAN   6JORDAN   MIDDLE EAST 23-453
3   Customer#000000003   MG9kdTD              ARGENTINA5ARGENTINAAMERICA     11-783
```

레이블/폭 페어의 순서는 테이블 열의 순서와 정확히 일치해야 합니다. 자세한 내용은 [FIXEDWIDTH](copy-parameters-data-format.md#copy-fixedwidth) 섹션을 참조하세요.

CUSTOMER 테이블 데이터용 고정 너비 사양 문자열은 다음과 같습니다.

```
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, 
c_region :12, c_phone:15,c_mktsegment:10'
```

고정 너비 데이터에서 CUSTOMER 테이블을 로드하려면 다음 명령을 실행합니다.

```
copy customer
from 's3://<your-bucket-name>/load/customer-fw.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, c_region :12, c_phone:15,c_mktsegment:10';
```

다음과 비슷한 오류 메시지가 표시됩니다.

```
An error occurred when executing the SQL command:
copy customer
from 's3://amzn-s3-demo-bucket/load/customer-fw.tbl'
credentials'...

ERROR: Load into table 'customer' failed.  Check 'stl_load_errors' system table for details. [SQL State=XX000] 

Execution time: 2.95s

1 statement(s) failed.
```
<a name="tutorial-loading-maxerror"></a>
**MAXERROR**  
기본적으로 COPY 실행 시 처음 오류가 발생할 때 명령이 실패하고 오류 메시지가 반환됩니다. 테스트 도중 시간을 절약하기 위해 MAXERROR 옵션을 사용하여 실패 전에 지정된 수의 오류를 건너뛰도록 COPY에 명령할 수 있습니다. CUSTOMER 테이블 데이터 로드를 처음 테스트할 때 오류를 예상하기 때문에 COPY 명령에 `maxerror 10`을 추가합니다.

FIXEDWIDTH 및 MAXERROR 옵션을 사용하여 테스트하려면 다음 명령을 실행합니다.

```
copy customer
from 's3://<your-bucket-name>/load/customer-fw.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, c_region :12, c_phone:15,c_mktsegment:10'
maxerror 10;
```

이번에는 오류 메시지 대신 다음과 비슷한 경고 메시지가 나타납니다.

```
Warnings:
Load into table 'customer' completed, 112497 record(s) loaded successfully.
Load into table 'customer' completed, 7 record(s) could not be loaded.  Check 'stl_load_errors' system table for details.
```

경고는 COPY 실행 시 일곱 번 오류가 발생했음을 나타냅니다. 오류를 확인하려면 다음 예에 나온 것처럼 STL\$1LOAD\$1ERRORS 테이블을 쿼리하세요.

```
select query, substring(filename,22,25) as filename,line_number as line, 
substring(colname,0,12) as column, type, position as pos, substring(raw_line,0,30) as line_text,
substring(raw_field_value,0,15) as field_text, 
substring(err_reason,0,45) as error_reason
from stl_load_errors 
order by query desc, filename 
limit 7;
```

STL\$1LOAD\$1ERRORS 쿼리 결과가 다음과 비슷해야 합니다.

```
 query  |         filename          | line |  column   |    type    | pos |           line_text           | field_text |              error_reason
--------+---------------------------+------+-----------+------------+-----+-------------------------------+------------+----------------------------------------------
 334489 | customer-fw.tbl.log       |    2 | c_custkey | int4       |  -1 | customer-fw.tbl               | customer-f | Invalid digit, Value 'c', Pos 0, Type: Integ
 334489 | customer-fw.tbl.log       |    6 | c_custkey | int4       |  -1 | Complete                      | Complete   | Invalid digit, Value 'C', Pos 0, Type: Integ
 334489 | customer-fw.tbl.log       |    3 | c_custkey | int4       |  -1 | #Total rows                   | #Total row | Invalid digit, Value '#', Pos 0, Type: Integ
 334489 | customer-fw.tbl.log       |    5 | c_custkey | int4       |  -1 | #Status                       | #Status    | Invalid digit, Value '#', Pos 0, Type: Integ
 334489 | customer-fw.tbl.log       |    1 | c_custkey | int4       |  -1 | #Load file                    | #Load file | Invalid digit, Value '#', Pos 0, Type: Integ
 334489 | customer-fw.tbl000        |    1 | c_address | varchar    |  34 | 1         Customer#000000001  | .Mayag.ezR | String contains invalid or unsupported UTF8
 334489 | customer-fw.tbl000        |    1 | c_address | varchar    |  34 | 1         Customer#000000001  | .Mayag.ezR | String contains invalid or unsupported UTF8
(7 rows)
```

결과를 검사하면 `error_reasons` 열에 2개의 메시지가 있음을 볼 수 있습니다.
+ 

  ```
  Invalid digit, Value '#', Pos 0, Type: Integ 
  ```

  이 오류의 원인은 `customer-fw.tbl.log` 파일입니다. 문제는 이것이 데이터 파일이 아니라 로그 파일이며, 로드되어서는 안 된다는 것입니다. 매니페스트 파일을 사용하면 잘못된 파일이 로드되는 것을 피할 수 있습니다.
+ 

  ```
  String contains invalid or unsupported UTF8 
  ```

  VARCHAR 데이터 형식은 최대 3바이트의 멀티바이트 UTF-8 문자를 지원합니다. 지원되지 않거나 잘못된 문자가 로드 데이터에 포함된 경우, ACCEPTINVCHARS 옵션을 사용하여 잘못된 각각의 문자를 지정된 다른 문자로 대체할 수 있습니다.

로드의 또 다른 문제는 감지하기가 더 어렵습니다. 로드로 인해 예기치 않은 결과가 발생했습니다. 이 문제를 조사하려면 다음 명령을 실행하여 CUSTOMER 테이블을 쿼리합니다.

```
select c_custkey, c_name, c_address        
from customer
order by c_custkey
limit 10;
```

```
 c_custkey |          c_name           |         c_address
-----------+---------------------------+---------------------------
         2 | Customer#000000002        | XSTf4,NCwDVaWNe6tE
         2 | Customer#000000002        | XSTf4,NCwDVaWNe6tE
         3 | Customer#000000003        | MG9kdTD
         3 | Customer#000000003        | MG9kdTD
         4 | Customer#000000004        | XxVSJsL
         4 | Customer#000000004        | XxVSJsL
         5 | Customer#000000005        | KvpyuHCplrB84WgAi
         5 | Customer#000000005        | KvpyuHCplrB84WgAi
         6 | Customer#000000006        | sKZz0CsnMD7mp4Xd0YrBvx
         6 | Customer#000000006        | sKZz0CsnMD7mp4Xd0YrBvx
(10 rows)
```

행들이 고유해야 하지만 중복된 행이 있습니다.

예상치 못한 결과를 검사하는 또 다른 방법은 로드된 행의 수를 확인하는 것입니다. 이 경우, 100,000개의 행이 로드되어야 하지만 로드 메시지는 112,497개의 레코드를 로드했다고 보고했습니다. 이 여분의 행은 불필요한 파일인 `customer-fw.tbl0000.bak`을 COPY가 로드했기 때문에 로드되었습니다.

이 연습에서는 잘못된 파일이 로드되는 것을 방지하기 위해 매니페스트 파일을 사용합니다.
<a name="tutorial-loading-acceptinvchars"></a>
**ACCEPTINVCHARS**  
기본적으로 COPY는 열의 데이터 형식이 지원하지 않는 문자가 있으면 행을 건너뛰고 오류를 반환합니다. 잘못된 UTF-8 문자에 대한 자세한 내용은 [멀티바이트 문자 로드 오류](multi-byte-character-load-errors.md) 섹션을 참조하세요.

MAXERRORS 옵션을 사용하여 오류를 무시하고 로드를 계속한 다음 STL\$1LOAD\$1ERRORS를 쿼리해 잘못된 문자를 찾은 후 데이터 파일을 수정할 수 있습니다. 하지만 MAXERRORS는 로드 문제 해결에 사용하는 것이 가장 좋으며, 일반적으로 프로덕션 환경에서는 사용하지 말아야 합니다.

잘못된 문자를 관리하는 데는 일반적으로 ACCEPTINVCHARS 옵션을 택하는 것이 더 좋습니다. ACCEPTINVCHARS는 COPY에게 잘못된 각 문자를 지정된 유효한 문자로 대체하고 로드 작업을 계속하라고 명령합니다. NULL을 제외한 어떤 ASCII 문자도 대체 문자로 지정할 수 있습니다. 기본 대체 문자는 물음표(?)입니다. COPY는 멀티바이트 문자를 같은 길이의 대체 문자열로 대체합니다. 예를 들어 4바이트 문자는 `'????'`로 대체됩니다.

COPY는 유효하지 않은 UTF-8 문자가 포함된 행 수를 반환합니다. 또한 영향을 받는 각 행에 대해 STL\$1REPLACEMENTS 시스템 테이블에 노드 조각당 최대 100행까지 항목을 추가합니다. 이후 추가되는 잘못된 UTF-8 문자 역시 변경되지만 이러한 문자의 변경 이벤트는 기록되지 않습니다.

ACCEPTINVCHARS는 VARCHAR 열에서만 유효합니다.

이 단계에서는 대체 문자 `'^'`과 함께 ACCEPTINVCHARS를 추가합니다.
<a name="tutorial-loading-manifest"></a>
**MANIFEST**  
키 접두사를 사용하여 Amazon S3에서 COPY를 실행할 때는 원치 않는 테이블이 로드될 위험이 있습니다. 예를 들어 `'s3://amzn-s3-demo-bucket/load/` 폴더에는 키 접두사 `customer-fw.tbl`: `customer-fw.tbl0000`, `customer-fw.tbl0001` 등을 공유하는 8개의 데이터 파일이 포함되어 있습니다. 하지만 같은 폴더에 불필요한 파일인 `customer-fw.tbl.log`와 `customer-fw.tbl-0001.bak`도 포함되어 있습니다.

올바른 파일만 모두 로드하려면 매니페스트 파일을 사용하세요. 매니페스트는 로드할 각 원본 파일의 고유한 객체 키를 명시적으로 나열하는 JSON 형식의 텍스트 파일입니다. 파일 객체는 서로 다른 폴더나 버킷에 있을 수 있지만 리전은 같아야 합니다. 자세한 내용은 [MANIFEST](copy-parameters-data-source-s3.md#copy-manifest) 섹션을 참조하세요.

다음은 `customer-fw-manifest` 텍스트를 보여줍니다.

```
{
  "entries": [
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-000"},
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-001"},
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-002"},
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-003"},
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-004"},    
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-005"},
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-006"}, 
    {"url":"s3://<your-bucket-name>/load/customer-fw.tbl-007"} 
    ]
}
```

**매니페스트 파일을 사용하여 CUSTOMER 테이블의 데이터를 로드하려면**

1. 텍스트 편집기에서 파일을 엽니다.`customer-fw-manifest`

1. *<your-bucket-name>*을 버킷의 이름으로 바꿉니다.

1. 파일을 저장합니다.

1. 파일을 버킷의 로드 폴더에 업로드합니다.

1. 다음 COPY 명령을 실행합니다.

   ```
   copy customer from 's3://<your-bucket-name>/load/customer-fw-manifest'
   credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
   fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, c_region :12, c_phone:15,c_mktsegment:10'
   maxerror 10 
   acceptinvchars as '^'
   manifest;
   ```

#### DATEFORMAT을 사용하여 DWDATE 테이블 로드
<a name="tutorial-loading-load-dwdate"></a>

이 단계에서는 DELIMITER 및 DATEFORMAT 옵션을 사용하여 DWDATE 테이블을 로드합니다.

DATE 및 TIMESTAMP 열을 로드할 때 COPY는 기본 형식(날짜는 YYYY-MM-DD, 타임스탬프는 YYYY-MM-DD HH:MI:SS)을 예상합니다. 로드 데이터가 기본 형식을 사용하지 않는 경우, DATEFORMAT 및 TIMEFORMAT을 사용하여 형식을 지정할 수 있습니다.

발췌한 다음 예는 DWDATE 테이블의 날짜 형식을 보여 줍니다. 열 2의 날짜 형식이 일관되지 않다는 점을 눈여겨보세요.

```
19920104	1992-01-04          Sunday		January	1992	199201	Jan1992	1	4	4	1...
19920112	January 12, 1992	Monday		January	1992	199201	Jan1992	2	12	12	1...
19920120	January 20, 1992	Tuesday	    January	1992	199201	Jan1992	3	20	20	1...
```
<a name="tutorial-loading-dateformat"></a>
**DATEFORMAT**  
날짜 형식은 하나만 지정할 수 있습니다. 로드 데이터에 서로 다른 열에서 일관되지 않은 형식이 포함되어 있거나 형식이 로드 시에 알려지지 않은 경우, `'auto'` 인수와 함께 DATEFORMAT을 사용합니다. `'auto'`가 지정되면 COPY는 유효한 날짜 또는 시간 형식을 인식하여 이를 기본 형식으로 변환합니다. `'auto'` 옵션은 DATEFORMAT 및 TIMEFORMAT 문자열 사용 시 지원되지 않는 몇 가지 형식을 인식합니다. 자세한 내용은 [DATEFORMAT 및 TIMEFORMAT 옵션의 자동 인식 사용](automatic-recognition.md) 섹션을 참조하세요.

DWDATE 테이블을 로드하려면 다음 COPY 명령을 실행합니다.

```
copy dwdate from 's3://<your-bucket-name>/load/dwdate-tab.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
delimiter '\t' 
dateformat 'auto';
```

#### 여러 데이터 파일 로드
<a name="tutorial-loading-load-lineorder"></a>

GZIP 및 COMPUPDATE 옵션을 사용하여 테이블을 로드할 수 있습니다.

단일 데이터 파일 또는 여러 파일에서 테이블을 로드할 수 있습니다. 이렇게 하면 두 방법의 로드 시간을 비교할 수 있습니다.
<a name="tutorial-loading-gzip-lzop"></a>
**GZIP, LZOP 및 BZIP2**  
gzip, lzop 또는 bzip2 압축 형식을 사용하여 파일을 압축할 수 있습니다. 압축된 파일에서 로드하면 COPY가 로드 프로세스 중에 파일 압축을 해제합니다. 파일을 압축하면 스토리지 공간이 절약되고 업로드 시간이 단축됩니다.
<a name="tutorial-loading-compupdate"></a>
**COMPUPDATE**  
압축 인코딩 없는 빈 테이블을 로드하는 경우, COPY는 로드 데이터를 분석하여 최적의 인코딩을 결정합니다. 그런 다음 로드를 시작하기 전에 이러한 인코딩을 사용하도록 테이블을 변경합니다. 이 분석 프로세스는 시간이 걸리지만 테이블당 최대 한 번 실행됩니다. 시간을 절약하려면 COMPUPDATE를 꺼서 이 단계를 건너뛸 수 있습니다. COPY 시간의 정확한 평가가 가능하도록 하려면 이 단계에서 COMPUPDATE를 끄세요.
<a name="tutorial-loading-multiple-files"></a>
**여러 파일**  
COPY 명령은 단일 파일에서 로드하는 대신 여러 파일에서 데이터를 병렬로 로드할 때 데이터를 매우 효율적으로 로드할 수 있습니다. 파일 수가 클러스터에 있는 조각 수의 배수가 되도록 데이터를 파일로 분할할 수 있습니다. 이 경우 Amazon Redshift는 워크로드를 분할하고 슬라이스 간에 데이터를 균등하게 배포합니다. 노드당 조각 수는 클러스터의 노드 크기에 따라 달라집니다. 각 노드 크기의 슬라이스 수에 대한 자세한 내용은 *Amazon Redshift 관리 가이드*의 [클러스터 및 노드 정보](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#rs-about-clusters-and-nodes) 섹션을 참조하세요.

예를 들어 이 자습서에서 사용하는 클러스터의 컴퓨팅 노드는 각각 2개의 조각을 가질 수 있습니다. 따라서 4노드 클러스터의 조각은 총 8개입니다. 앞 단계에서는 파일이 매우 작음에도 불구하고 여덟 개의 파일에 로드 데이터가 포함되었습니다. 큰 단일 파일에서 로드할 때와 여러 파일에서 로드할 때의 시간 차이를 비교할 수 있습니다.

1,500만 개의 레코드를 포함하고 약 1.2GB를 차지하는 파일도 Amazon Redshift의 규모에서는 매우 작습니다. 그러나 이 파일들은 여러 파일에서 로드할 경우의 성능상 장점을 보여 주는 데는 충분합니다.

다음 이미지는 LINEORDER를 위한 데이터 파일을 보여줍니다.

![\[LINEORDER 테이블의 데이터는 9개의 파일로 분할됩니다.\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/images/tutorial-load-lineorder-files.png)


**여러 파일에서의 COPY 성능을 평가하려면**

1. 실험실 테스트에서 다음 명령을 실행하여 단일 파일에서 COPY 작업을 수행했습니다. 이 명령은 가상의 버킷을 보여줍니다.

   ```
   copy lineorder from 's3://amzn-s3-demo-bucket/load/lo/lineorder-single.tbl' 
   credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
   gzip
   compupdate off
   region 'us-east-1';
   ```

1. 결과는 다음과 같았습니다. 실행 시간을 적어 둡니다.

   ```
   Warnings:
   Load into table 'lineorder' completed, 14996734 record(s) loaded successfully.
   
   0 row(s) affected.
   copy executed successfully
   
   Execution time: 51.56s
   ```

1. 그런 다음, 다음 명령을 실행하여 여러 파일에서 COPY 명령을 실행했습니다.

   ```
   copy lineorder from 's3://amzn-s3-demo-bucket/load/lo/lineorder-multi.tbl' 
   credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>' 
   gzip
   compupdate off
   region 'us-east-1';
   ```

1. 결과는 다음과 같았습니다. 실행 시간을 적어 둡니다.

   ```
   Warnings:
   Load into table 'lineorder' completed, 14996734 record(s) loaded successfully.
   
   0 row(s) affected.
   copy executed successfully
   
   Execution time: 17.7s
   ```

1. 실행 시간을 비교합니다.

   이 실험에서는 1,500만 개의 레코드를 로드하는 시간이 51.56초에서 17.7초로 줄어들어 65.7% 단축되었습니다.

   이 결과는 4노드 클러스터 사용을 기준으로 한 것입니다. 클러스터에 더 많은 노드가 있는 경우, 시간이 더욱 단축됩니다. 수십에서 수백 개의 노드가 있는 일반적인 Amazon Redshift 클러스터의 경우 이 차이는 더 크게 벌어집니다. 단일 노드 클러스터인 경우, 실행 시간의 차이가 거의 없습니다.

## 6단계: 데이터베이스 vacuum 및 분석
<a name="tutorial-loading-data-vacuum"></a>

상당히 많은 행을 추가, 삭제 또는 수정할 때마다 VACUUM 명령을 실행한 다음 ANALYZE 명령을 실행해야 합니다. *vacuum*은 삭제된 행에서 스페이스를 회수하고 정렬 순서를 복원합니다. ANALYZE 명령은 통계 메타데이터를 업데이트하므로 쿼리 옵티마이저가 더 정확한 쿼리 계획을 생성할 수 있습니다. 자세한 내용은 [테이블 Vacuum](t_Reclaiming_storage_space202.md) 섹션을 참조하세요.

데이터를 정렬 키 순서로 로드하는 경우에는 vacuum이 빠릅니다. 이 자습서에서 상당히 많은 행을 추가했지만 빈 테이블에 추가한 것입니다. 따라서 재정렬할 필요가 없고 삭제한 행도 없습니다. COPY는 빈 테이블을 로드한 후 자동으로 통계를 업데이트하므로 통계는 최신 상태입니다. 다만 깔끔한 정리를 위해 데이터베이스에 대해 vacuum을 수행하고 분석하여 이 자습서를 마치세요.

데이터베이스를 vacuum하고 분석하려면 다음 명령을 실행합니다.

```
vacuum;
analyze;
```

## 7단계: 리소스 정리
<a name="tutorial-loading-data-clean-up"></a>

클러스터는 실행하는 동안 계속해서 요금이 발생합니다. 이 튜토리얼을 완료하면 *Amazon Redshift 시작 안내서*의 [5단계: 액세스 취소 및 샘플 클러스터 삭제](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-clean-up-tasks.html) 단계에 따라 환경을 이전 상태로 되돌려야 합니다.

클러스터를 유지하면서 SSB 테이블에서 사용한 스토리지를 복원하고 싶다면 다음 명령을 실행하세요.

```
drop table part;
drop table supplier;
drop table customer;
drop table dwdate;
drop table lineorder;
```

### 다음
<a name="tutorial-loading-next-summary"></a>

[요약](#tutorial-loading-data-summary)

## 요약
<a name="tutorial-loading-data-summary"></a>

이 튜토리얼에서는 데이터 파일을 Amazon S3에 업로드한 다음 COPY 명령을 사용하여 파일에서 Amazon Redshift 테이블로 데이터를 로드했습니다.

데이터를 로드할 때 사용한 형식은 다음과 같습니다.
+ 문자로 구분된 형식
+ CSV
+ 고정 너비 형식

STL\$1LOAD\$1ERRORS 시스템 테이블을 사용하여 로드 오류 문제를 해결한 다음 REGION, MANIFEST, MAXERROR, ACCEPTINVCHARS, DATEFORMAT 및 NULL AS 옵션을 사용하여 오류를 해결했습니다.

데이터 로드에 다음의 모범 사례를 적용했습니다.
+ [COPY 명령을 사용하여 데이터 로드](c_best-practices-use-copy.md)
+ [파일에서 데이터 로드](c_best-practices-use-multiple-files.md)
+ [단일 COPY 명령을 사용하여 여러 파일에서 로드](c_best-practices-single-copy-command.md)
+ [데이터 파일 압축](c_best-practices-compress-data-files.md)
+ [로드 전후의 데이터 파일 확인](c_best-practices-verifying-data-files.md)

Amazon Redshift 모범 사례에 대한 자세한 내용은 다음 링크를 참조하세요.
+ [데이터 로드에 대한 Amazon Redshift 모범 사례](c_loading-data-best-practices.md)
+ [Amazon Redshift 테이블 설계 모범 사례](c_designing-tables-best-practices.md) 
+ [Amazon Redshift 쿼리 설계 모범 사례](c_designing-queries-best-practices.md) 