

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

# 在 DynamoDB 中匯出、匯入和查詢資料的 Hive 命令範例
<a name="EMR_Hive_Commands"></a>

下列範例會使用 Hive 命令來執行各種操作，例如將資料匯出至 Amazon S3 或 HDFS、將資料匯入至 DynamoDB、聯結資料表、查詢資料表等。

Hive 資料表上的操作會參考儲存在 DynamoDB 中的資料。Hive 命令需遵守 DynamoDB 資料表的佈建輸送量設定，而其擷取的資料將包含 DynamoDB 在處理 Hive 操作請求時寫入 DynamoDB 資料表的資料。如果資料擷取程序花費的時間較長，Hive 命令傳回的部分資料可能會在 Hive 命令開始後又已於 DynamoDB 內更新。

Hive 命令 `DROP TABLE` 和 `CREATE TABLE` 僅對 Hive 中的本機資料表有效，因此無法在 DynamoDB 中建立或捨棄資料表。如果您的 Hive 查詢參考的是 DynamoDB 內的資料表，該資料表在您執行查詢前必須已經存在。如需有關在 DynamoDB 中建立和刪除資料表的詳細資訊，請參閱《Amazon DynamoDB 開發人員指南》**中的[使用 DynamoDB 中的資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html)。

**注意**  
 當您將 Hive 資料表映射至 Amazon S3 中的位置時，請勿將其映射至儲存貯體 s3：//amzn-s3-demo-bucket 的根路徑，因為這可能會在 Hive 將資料寫入 Amazon S3 時導致錯誤。而是將資料表對應至儲存貯體的子路徑，s3：//amzn-s3-demo-bucket/mypath。

## 從 DynamoDB 匯出資料
<a name="EMR_Hive_Commands_exporting"></a>

 您可以使用 Hive 從 DynamoDB 匯出資料。

**將 DynamoDB 資料表匯出至 Amazon S3 儲存貯體**
+  請建立用於參考儲存在 DynamoDB 中的資料的 Hive 資料表。接下來可以呼叫 INSERT OVERWRITE 命令，將資料寫入至外部目錄。在下列範例中，{{s3：//amzn-s3-demo-bucket/path/subpath/}} 是 Amazon S3 中的有效路徑。請調整 CREATE 命令中的資料欄和資料類型，以符合您 DynamoDB 中的值。您可以使用此方法在 Amazon S3 中建立 DynamoDB 資料的存檔。

  ```
  1. CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
  2. STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
  3. TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
  4. "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}");                   
  5.                     
  6. INSERT OVERWRITE DIRECTORY '{{s3://amzn-s3-demo-bucket/path/subpath/}}' SELECT * 
  7. FROM {{hiveTableName}};
  ```

**使用格式化將 DynamoDB 資料表匯出至 Amazon S3 儲存貯體**
+  建立用於參考 Amazon S3 中的位置的外部資料表。於下方顯示為 s3\_export。在呼叫 CREATE 期間，請指定資料表列的格式編排。然後，當您使用 INSERT OVERWRITE 從 DynamoDB 匯出資料至 s3\_export 時，資料就會以指定的格式寫出。在以下範例中，資料是以逗號分隔值 (CSV) 的格式寫出。

  ```
   1. CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
   2. STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
   3. TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
   4. "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}");                      
   5.                     
   6. CREATE EXTERNAL TABLE {{s3_export}}({{a_col string, b_col bigint, c_col array<string>}})
   7. ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
   8. LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}';
   9.                     
  10. INSERT OVERWRITE TABLE {{s3_export}} SELECT * 
  11. FROM {{hiveTableName}};
  ```

**將 DynamoDB 資料表匯出至 Amazon S3 儲存貯體而不指定資料欄映射**
+  請建立用於參考儲存在 DynamoDB 中的資料的 Hive 資料表。與前述的範例類似，只是不用指定欄位的映射。此資料表必須僅有 `map<string, string>` 類型的一欄。如果您隨後在 Amazon S3 中建立 `EXTERNAL` 資料表，即可呼叫 `INSERT OVERWRITE` 命令，將資料從 DynamoDB 寫入至 Amazon S3。您可以使用此方法在 Amazon S3 中建立 DynamoDB 資料的存檔。由於並未映射欄位，您無法查詢以此方式匯出的資料表。Hive 0.8.1.5 或更新版本能夠不指定資料欄映射即匯出資料，而 Amazon EMR AMI 2.2.*x* 及更新版本也可支援此功能。

  ```
   1. CREATE EXTERNAL TABLE {{hiveTableName}} (item map<string,string>)
   2. STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
   3. TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}");  
   4.     
   5. CREATE EXTERNAL TABLE s3TableName (item map<string, string>)
   6. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
   7. LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}'; 
   8.                 
   9. INSERT OVERWRITE TABLE {{s3TableName}} SELECT * 
  10. FROM {{hiveTableName}};
  ```

**使用資料壓縮將 DynamoDB 資料表匯出至 Amazon S3 儲存貯體**
+  Hive 提供了多種壓縮轉碼器，您可以在 Hive 工作階段期間設定。如此會將匯出的資料以指定格式壓縮。以下範例會使用 Lempel-Ziv-Oberhumer (LZO) 演算法壓縮匯出的檔案。

  ```
   1. SET hive.exec.compress.output=true;
   2. SET io.seqfile.compression.type=BLOCK;
   3. SET mapred.output.compression.codec = com.hadoop.compression.lzo.LzopCodec;                    
   4.                     
   5. CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
   6. STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
   7. TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
   8. "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}");                    
   9.                     
  10. CREATE EXTERNAL TABLE {{lzo_compression_table}} (line STRING)
  11. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
  12. LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}';
  13.                     
  14. INSERT OVERWRITE TABLE {{lzo_compression_table}} SELECT * 
  15. FROM {{hiveTableName}};
  ```

   可用的壓縮轉碼器為：
  +  org.apache.hadoop.io.compress.GzipCodec 
  +  org.apache.hadoop.io.compress.DefaultCodec 
  +  com.hadoop.compression.lzo.LzoCodec 
  +  com.hadoop.compression.lzo.LzopCodec 
  +  org.apache.hadoop.io.compress.BZip2Codec 
  +  org.apache.hadoop.io.compress.SnappyCodec 

**將 DynamoDB 資料表匯出至 HDFS**
+  請使用下列 Hive 命令。其中 {{hdfs:///directoryName}} 是有效的 HDFS 路徑，{{hiveTableName}} 則是 Hive 中參考 DynamoDB 的資料表。Hive 0.7.1.1 在將資料匯出至 Amazon S3 時，會採用 HDFS 做為中間步驟，因此這個匯出操作的速度比匯出 DynamoDB 資料表至 Amazon S3 更快速。以下範例也說明了如何將 `dynamodb.throughput.read.percent` 設為 1.0，以提高讀取請求率。

  ```
  1. CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
  2. STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
  3. TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
  4. "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}"); 
  5.                     
  6. SET dynamodb.throughput.read.percent=1.0;                    
  7.                     
  8. INSERT OVERWRITE DIRECTORY '{{hdfs:///directoryName}}' SELECT * FROM {{hiveTableName}};
  ```

   您也可以使用前述匯出至 Amazon S3 的格式編排和壓縮等方式，將資料匯出至 HDFS。若要如此，只需將上述範例中的 Amazon S3 目錄變更為 HDFS 目錄即可。<a name="EMR_Hive_non-printable-utf8"></a>

**在 Hive 中讀取不可列印的 UTF-8 字元資料**
+ 您可以在建資料表時使用 `STORED AS SEQUENCEFILE` 子句，以 Hive 讀取和寫入不可列印的 UTF-8 字元資料。SequenceFile 為 Hadoop 二進位檔案格式，您需要使用 Hadoop 來讀取此檔。下列範例顯示如何將資料從 DynamoDB 匯出到 Amazon S3。您可以使用此功能處理不可列印的 UTF-8 編碼字元。

  ```
   1. CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
   2. STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
   3. TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
   4. "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}");                      
   5.                     
   6. CREATE EXTERNAL TABLE {{s3_export}}({{a_col string, b_col bigint, c_col array<string>}})
   7. STORED AS SEQUENCEFILE
   8. LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}';
   9.                     
  10. INSERT OVERWRITE TABLE {{s3_export}} SELECT * 
  11. FROM {{hiveTableName}};
  ```

## 將資料匯入 DynamoDB
<a name="EMR_Hive_Commands_importing"></a>

 在使用 Hive 將資料寫入 DynamoDB 時，您應確保寫入容量單位數大於叢集中的映射器數量。例如，在 m1.xlarge EC2 執行個體上執行的叢集會在每個執行個體上產生 8 個映射器。而含有 10 個執行個體的叢集，則代表總共會有 80 個映射器。如果您寫入容量單位未超過叢集中的映射器數量，Hive 寫入操作可能會耗用所有寫入輸送量，或企圖使用比所佈建的量更多的輸送量。如需各 EC2 執行個體類型產生的映射器數量的詳細資訊，請參閱 [設定 Hadoop](emr-hadoop-config.md)。

 Hadoop 中的映射器數量會受到輸入分割的控制。若輸入分割的數量過少，則您的寫入命令可能會無法使用資料表中所有可用的寫入輸送量。

 如果目標 DynamoDB 資料表中已存在具有相同金鑰的項目，則會覆寫此項目。如果目標 DynamoDB 資料表中不存在具有金鑰的項目，則會插入此項目。

**將資料表從 Amazon S3 匯入 DynamoDB**
+  您可以使用 Amazon EMR 和 Hive 將資料從 Amazon S3 寫入至 DynamoDB。

  ```
  CREATE EXTERNAL TABLE {{s3_import}}({{a_col string, b_col bigint, c_col array<string>}})
  ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
  LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}';                    
                      
  CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
  TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
  "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}");  
                      
  INSERT OVERWRITE TABLE {{hiveTableName}} SELECT * FROM {{s3_import}};
  ```

**將資料表從 Amazon S3 儲存貯體匯入 DynamoDB 而不指定資料欄映射**
+  請建立一個 `EXTERNAL` 資料表，用於參考先前從 DynamoDB 匯出並儲存在 Amazon S3 中的資料。在開始匯入前，確保 DynamoDB 中已有該資料表，且其具備的索引鍵結構描述與先前匯出的 DynamoDB 資料表相同。此外，該資料表僅能有 `map<string, string>` 類型的一欄。如果您隨後建立了連結到 DynamoDB 的 Hive 資料表，即可呼叫 `INSERT OVERWRITE` 命令，將資料從 Amazon S3 寫入至 DynamoDB。由於並未映射欄位，您無法查詢以此方式匯入的資料表。Hive 0.8.1.5 或更新版本能夠不指定資料欄映射即匯入資料，Amazon EMR AMI 2.2.3 和更新版本可支援。

  ```
  CREATE EXTERNAL TABLE s3TableName (item map<string, string>)
  ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
  LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}'; 
                          
  CREATE EXTERNAL TABLE {{hiveTableName}} (item map<string,string>)
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
  TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}");  
                   
  INSERT OVERWRITE TABLE {{hiveTableName}} SELECT * 
  FROM {{s3TableName}};
  ```

**將資料表從 HDFS 匯入 DynamoDB**
+  您可以使用 Amazon EMR 和 Hive，以將資料從 HDFS 寫入至 DynamoDB。

  ```
  CREATE EXTERNAL TABLE {{hdfs_import}}({{a_col string, b_col bigint, c_col array<string>}})
  ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
  LOCATION '{{hdfs:///directoryName}}';                    
                      
  CREATE EXTERNAL TABLE {{hiveTableName}} ({{col1 string, col2 bigint, col3 array<string>}})
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
  TBLPROPERTIES ("dynamodb.table.name" = "{{dynamodbtable1}}", 
  "dynamodb.column.mapping" = "{{col1:name,col2:year,col3:holidays}}");  
                      
  INSERT OVERWRITE TABLE {{hiveTableName}} SELECT * FROM {{hdfs_import}};
  ```

## 查詢 DynamoDB 中的資料
<a name="EMR_Hive_Commands_querying"></a>

 下列範例會顯示數種方式，以供您使用 Amazon EMR 查詢儲存在 DynamoDB 中的資料。

**尋找映射欄 (`max`) 中的最大值**
+  請使用 Hive 命令，如下所示。在第一個命令中，CREATE 陳述式建立了一個參考儲存在 DynamoDB 內資料的 Hive 資料表。SELECT 陳述式接下來會使用該資料表查詢儲存在 DynamoDB 內的資料。以下範例會尋找指定客戶所下的最大訂單。

  ```
  CREATE EXTERNAL TABLE {{hive_purchases}}({{customerId bigint, total_cost double, items_purchased array<String>}}) 
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
  TBLPROPERTIES ("dynamodb.table.name" = "{{Purchases}}",
  "dynamodb.column.mapping" = "{{customerId:CustomerId,total_cost:Cost,items_purchased:Items}}");
  
  SELECT max(total_cost) from hive_purchases where customerId = 717;
  ```

**使用 `GROUP BY` 子句彙總資料**
+  您可以使用 `GROUP BY` 子句跨多筆記錄收集資料。這通常會用於 sum、count、min 或 max 等彙總函數。下方範例會以購買三次以上的客戶為主，傳回最大訂單清單。

  ```
  CREATE EXTERNAL TABLE {{hive_purchases}}({{customerId bigint, total_cost double, items_purchased array<String>}}) 
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
  TBLPROPERTIES ("dynamodb.table.name" = "{{Purchases}}",
  "dynamodb.column.mapping" = "{{customerId:CustomerId,total_cost:Cost,items_purchased:Items}}");
  
  SELECT customerId, max(total_cost) from hive_purchases GROUP BY customerId HAVING count(*) > 3;
  ```

**聯結兩個 DynamoDB 資料表**
+  下列範例會將兩個 Hive 資料表映射至儲存在 DynamoDB 中的資料。然後會呼叫這兩個資料表的聯結。聯結會在叢集上運算並傳回。聯結不會在 DynamoDB 中發生。此範例會傳回下訂兩筆以上訂單的客戶和其購買項目的清單。

  ```
  CREATE EXTERNAL TABLE {{hive_purchases}}({{customerId bigint, total_cost double, items_purchased array<String>}}) 
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
  TBLPROPERTIES ("dynamodb.table.name" = "{{Purchases}}",
  "dynamodb.column.mapping" = "{{customerId:CustomerId,total_cost:Cost,items_purchased:Items}}");
  
  CREATE EXTERNAL TABLE {{hive_customers}}({{customerId bigint, customerName string, customerAddress array<String>}}) 
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
  TBLPROPERTIES ("dynamodb.table.name" = "{{Customers}}",
  "dynamodb.column.mapping" = "{{customerId:CustomerId,customerName:Name,customerAddress:Address}}");
  
  Select c.customerId, c.customerName, count(*) as count from hive_customers c 
  JOIN hive_purchases p ON c.customerId=p.customerId 
  GROUP BY c.customerId, c.customerName HAVING count > 2;
  ```

**聯節來自不同來源的兩個資料表**
+  在下列範例中，Customer\_S3 是 Hive 資料表，其可載入儲存在 Amazon S3 中的 CSV 檔案；hive\_purchases 則是用於參考 DynamoDB 中的資料的資料表。下列範例會將 Amazon S3 中儲存為 CSV 檔案的客戶資料與 DynamoDB 中儲存的訂單資料互相聯結，然後傳回一組訂單資料，其為姓名中有 "Miller" 一字的客戶所下訂。

  ```
  CREATE EXTERNAL TABLE {{hive_purchases}}({{customerId bigint, total_cost double, items_purchased array<String>}}) 
  STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
  TBLPROPERTIES ("dynamodb.table.name" = "{{Purchases}}",
  "dynamodb.column.mapping" = "{{customerId:CustomerId,total_cost:Cost,items_purchased:Items}}");
  
  CREATE EXTERNAL TABLE {{Customer_S3}}(customerId bigint, customerName string, customerAddress array<String>)
  ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
  LOCATION '{{s3://amzn-s3-demo-bucket/path/subpath/}}';
  
  Select c.customerId, c.customerName, c.customerAddress from 
  Customer_S3 c 
  JOIN hive_purchases p 
  ON c.customerid=p.customerid 
  where c.customerName like '%Miller%';
  ```

**注意**  
 在上述每個範例中，均加入了 CREATE TABLE 陳述式，以求清晰明瞭和完整性。針對指定的 Hive 資料表執行多向查詢或匯出操作時，僅需在 Hive 工作階段開始時建立一次資料表。