

# DynamoDB와 HDFS 간 데이터 복사
<a name="EMRforDynamoDB.CopyingData.HDFS"></a>

DynamoDB 테이블에 데이터가 있을 경우 Hive를 사용하여 이 데이터를 Hadoop 분산 파일 시스템(HDFS)으로 복사할 수 있습니다.

DynamoDB의 데이터가 필요한 MapReduce 작업을 실행하는 경우 이렇게 할 수 있습니다. DynamoDB에서 HDFS로 데이터를 복사하는 경우 Hadoop이 Amazon EMR 클러스터에서 사용 가능한 모든 노드를 병렬로 사용하여 이 작업을 처리할 수 있습니다. MapReduce 작업이 완료되면 HDFS에서 DDB로 결과를 쓸 수 있습니다.

다음 예제에서는 Hive가 다음 HDFS 디렉터리에서 데이터를 읽고 씁니다. `/user/hadoop/hive-test` 

**참고**  
이 단원의 예제는 [자습서: Amazon DynamoDB 및 Apache Hive 작업](EMRforDynamoDB.Tutorial.md)의 단계를 완료했고 DynamoDB에 *ddb\$1features*라는 외부 테이블이 있다는 전제하에 작성되었습니다.

**Topics**
+ [Hive 기본 형식을 사용하여 데이터 복사](#EMRforDynamoDB.CopyingData.HDFS.DefaultFormat)
+ [사용자 지정 형식을 사용하여 데이터 복사](#EMRforDynamoDB.CopyingData.HDFS.UserSpecifiedFormat)
+ [열 매핑 없이 데이터 복사](#EMRforDynamoDB.CopyingData.HDFS.NoColumnMapping)
+ [HDFS의 데이터 액세스](#EMRforDynamoDB.CopyingData.HDFS.ViewingData)

## Hive 기본 형식을 사용하여 데이터 복사
<a name="EMRforDynamoDB.CopyingData.HDFS.DefaultFormat"></a>

**Example DynamoDB에서 HDFS로**  
`INSERT OVERWRITE` 문을 사용하여 HDFS에 직접 쓰기를 수행합니다.  

```
INSERT OVERWRITE DIRECTORY 'hdfs:///user/hadoop/hive-test'
SELECT * FROM ddb_features;
```
HDFS 내 데이터 파일은 다음과 같습니다.  

```
920709^ASoldiers Farewell Hill^ASummit^ANM^A32.3564729^A-108.33004616135
1178153^AJones Run^AStream^APA^A41.2120086^A-79.25920781260
253838^ASentinel Dome^ASummit^ACA^A37.7229821^A-119.584338133
264054^ANeversweet Gulch^AValley^ACA^A41.6565269^A-122.83614322900
115905^AChacaloochee Bay^ABay^AAL^A30.6979676^A-87.97388530
```
각 필드는 SOH 문자(제목 시작 부분, 0x01)로 구분됩니다. 파일에서는 SOH가 **^A**로 나타납니다.

**Example HDFS에서 DynamoDB로**  

1. HDFS 내의 형식이 지정되지 않은 데이터로 매핑되는 외부 테이블을 생성합니다.

   ```
   CREATE EXTERNAL TABLE hdfs_features_unformatted
       (feature_id       BIGINT,
       feature_name      STRING ,
       feature_class     STRING ,
       state_alpha       STRING,
       prim_lat_dec      DOUBLE ,
       prim_long_dec     DOUBLE ,
       elev_in_ft        BIGINT)
   LOCATION 'hdfs:///user/hadoop/hive-test';
   ```

1. DynamoDB에 데이터를 복사합니다.

   ```
   INSERT OVERWRITE TABLE ddb_features
   SELECT * FROM hdfs_features_unformatted;
   ```

## 사용자 지정 형식을 사용하여 데이터 복사
<a name="EMRforDynamoDB.CopyingData.HDFS.UserSpecifiedFormat"></a>

다른 필드 구분자 문자를 지정하려면 HDFS 디렉터리로 매핑되는 외부 테이블을 생성할 수 있습니다. 쉼표로 분리된 값(CSV)을 갖는 데이터 파일을 생성할 때 이 기법을 사용할 수 있습니다.

**Example DynamoDB에서 HDFS로**  

1. HDFS로 매핑되는 Hive 외부 테이블을 생성합니다. 이때 데이터 형식이 DynamoDB 외부 테이블과 일치해야 합니다.

   ```
   CREATE EXTERNAL TABLE hdfs_features_csv
       (feature_id       BIGINT,
       feature_name      STRING ,
       feature_class     STRING ,
       state_alpha       STRING,
       prim_lat_dec      DOUBLE ,
       prim_long_dec     DOUBLE ,
       elev_in_ft        BIGINT)
   ROW FORMAT DELIMITED
   FIELDS TERMINATED BY ','
   LOCATION 'hdfs:///user/hadoop/hive-test';
   ```

1. DynamoDB에서 데이터를 복사합니다.

   ```
   INSERT OVERWRITE TABLE hdfs_features_csv
   SELECT * FROM ddb_features;
   ```
HDFS 내 데이터 파일은 다음과 같습니다.  

```
920709,Soldiers Farewell Hill,Summit,NM,32.3564729,-108.3300461,6135
1178153,Jones Run,Stream,PA,41.2120086,-79.2592078,1260
253838,Sentinel Dome,Summit,CA,37.7229821,-119.58433,8133
264054,Neversweet Gulch,Valley,CA,41.6565269,-122.8361432,2900
115905,Chacaloochee Bay,Bay,AL,30.6979676,-87.9738853,0
```

**Example HDFS에서 DynamoDB로**  
단일 HiveQL 문을 사용하여 DynamoDB 테이블을 HDFS의 데이터로 채울 수 있습니다.  

```
INSERT OVERWRITE TABLE ddb_features
SELECT * FROM hdfs_features_csv;
```

## 열 매핑 없이 데이터 복사
<a name="EMRforDynamoDB.CopyingData.HDFS.NoColumnMapping"></a>

데이터 형식 또는 열 매핑을 지정하지 않고 DynamoDB의 데이터를 원본 형식으로 복사하여 HDFS에 쓸 수 있습니다. 이 방법을 사용하여 DynamoDB 데이터의 아카이브를 생성하고 HDFS에 저장할 수 있습니다.



**참고**  
DynamoDB 테이블에 맵, 목록, 부울 또는 Null 형식의 속성이 포함된 경우 이것이 Hive를 사용하여 DynamoDB에서 HDFS로 데이터를 복사할 수 있는 유일한 방법입니다.

**Example DynamoDB에서 HDFS로**  

1. DynamoDB 테이블과 연결된 외부 테이블을 생성합니다. (이 HiveQL 문에는 `dynamodb.column.mapping`이 없습니다.)

   ```
   CREATE EXTERNAL TABLE ddb_features_no_mapping
       (item MAP<STRING, STRING>)
   STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
   TBLPROPERTIES ("dynamodb.table.name" = "Features");
   ```

   

1. HDFS 디렉터리와 연결된 또 하나의 외부 테이블을 생성합니다.

   ```
   CREATE EXTERNAL TABLE hdfs_features_no_mapping
       (item MAP<STRING, STRING>)
   ROW FORMAT DELIMITED
   FIELDS TERMINATED BY '\t'
   LINES TERMINATED BY '\n'
   LOCATION 'hdfs:///user/hadoop/hive-test';
   ```

1. DynamoDB에서 HDFS로 데이터를 복사합니다.

   ```
   INSERT OVERWRITE TABLE hdfs_features_no_mapping
   SELECT * FROM ddb_features_no_mapping;
   ```
HDFS 내 데이터 파일은 다음과 같습니다.  

```
Name^C{"s":"Soldiers Farewell Hill"}^BState^C{"s":"NM"}^BClass^C{"s":"Summit"}^BElevation^C{"n":"6135"}^BLatitude^C{"n":"32.3564729"}^BId^C{"n":"920709"}^BLongitude^C{"n":"-108.3300461"}
Name^C{"s":"Jones Run"}^BState^C{"s":"PA"}^BClass^C{"s":"Stream"}^BElevation^C{"n":"1260"}^BLatitude^C{"n":"41.2120086"}^BId^C{"n":"1178153"}^BLongitude^C{"n":"-79.2592078"}
Name^C{"s":"Sentinel Dome"}^BState^C{"s":"CA"}^BClass^C{"s":"Summit"}^BElevation^C{"n":"8133"}^BLatitude^C{"n":"37.7229821"}^BId^C{"n":"253838"}^BLongitude^C{"n":"-119.58433"}
Name^C{"s":"Neversweet Gulch"}^BState^C{"s":"CA"}^BClass^C{"s":"Valley"}^BElevation^C{"n":"2900"}^BLatitude^C{"n":"41.6565269"}^BId^C{"n":"264054"}^BLongitude^C{"n":"-122.8361432"}
Name^C{"s":"Chacaloochee Bay"}^BState^C{"s":"AL"}^BClass^C{"s":"Bay"}^BElevation^C{"n":"0"}^BLatitude^C{"n":"30.6979676"}^BId^C{"n":"115905"}^BLongitude^C{"n":"-87.9738853"}
```
각 필드는 STX 문자(텍스트의 시작 부분, 0x02)로 시작하고 ETX 문자(텍스트의 끝부분, 0x03)로 끝납니다. 파일에서는 STX가 **^B**로 나타나고 ETX가 **^C**로 나타납니다.

**Example HDFS에서 DynamoDB로**  
단일 HiveQL 문을 사용하여 DynamoDB 테이블을 HDFS의 데이터로 채울 수 있습니다.  

```
INSERT OVERWRITE TABLE ddb_features_no_mapping
SELECT * FROM hdfs_features_no_mapping;
```

## HDFS의 데이터 액세스
<a name="EMRforDynamoDB.CopyingData.HDFS.ViewingData"></a>

HDFS는 Amazon EMR 클러스터의 모든 노드에서 액세스할 수 있는 분산 파일 시스템입니다. SSH를 사용하여 리더 노드에 연결하는 경우 명령줄 도구를 사용하여 Hive가 HDFS에 쓴 데이터에 액세스할 수 있습니다.

HDFS는 리더 노드의 로컬 파일 시스템과 동일한 것이 아닙니다. 표준 Linux 명령(예: `cat`, `cp`, `mv`, `rm`)을 사용하여 HDFS 내 파일 및 디렉터리에 대한 작업을 수행할 수 없습니다. `hadoop fs` 명령을 사용해야 합니다.

다음 단계는 이 단원에서 설명한 절차 중 하나를 사용하여 DynamoDB에서 HDFS로 데이터를 복사했다는 전제하에 작성되었습니다.

1. 현재 위치가 Hive 명령 프롬프트라면 Linux 명령 프롬프트로 전환합니다.

   ```
   hive> exit;
   ```

1. HDFS 내 /user/hadoop/hive-test 디렉터리의 내용을 나열합니다. (Hive가 DynamoDB에서 데이터를 복사하여 저장한 디렉터리입니다.)

   ```
   hadoop fs -ls /user/hadoop/hive-test
   ```

   응답이 다음과 비슷할 것입니다.

   ```
   Found 1 items
   -rw-r--r-- 1 hadoop hadoop 29504 2016-06-08 23:40 /user/hadoop/hive-test/000000_0
   ```

   파일 이름(*000000\$10*)은 시스템에 의해 생성됩니다.

1. 파일 내용을 확인합니다.

   ```
   hadoop fs -cat /user/hadoop/hive-test/000000_0
   ```
**참고**  
이 예제에서는 파일 용량이 비교적 작습니다(약 29KB). 용량이 매우 크거나 인쇄 불가능한 문자를 포함하는 파일에 이 명령을 사용할 때는 주의하세요.

1. (선택 사항) 데이터 파일을 HDFS에서 리더 노드의 로컬 파일 시스템으로 복사할 수 있습니다. 그런 다음 표준 Linux 명령줄 유틸리티를 사용하여 파일 데이터에 대한 작업을 수행할 수 있습니다.

   ```
   hadoop fs -get /user/hadoop/hive-test/000000_0
   ```

   이 명령은 파일을 덮어쓰지 않습니다.
**참고**  
리더 노드의 로컬 파일 시스템은 용량이 제한적입니다. 로컬 파일 시스템의 가용 용량보다 큰 파일에는 이 명령을 사용하지 마세요.