

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

# Amazon EMR 上 Hive 的差異和考量
<a name="emr-hive-differences"></a>

## Amazon EMR 上的 Apache Hive 與 Apache Hive 之間的差異
<a name="emr-hive-apache-diff"></a>

本章節描述了 Amazon EMR 上的 Hive 與 [http://svn.apache.org/viewvc/hive/branches/](http://svn.apache.org/viewvc/hive/branches/) 所提供之預設 Hive 版本之間的差異。

### Hive 授權
<a name="emr-hive-authorization"></a>

 Amazon EMR 支援 HDFS 的 [Hive 授權](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Authorization)，但針對 EMRFS 和 Amazon S3 則不支援。Amazon EMR 叢集會在預設停用授權的情況下執行。

### Amazon S3 的 Hive 檔案合併行為
<a name="emr-hive-filemerge"></a>

如果 `hive.merge.mapfiles` 是 true，Apache Hive 會在僅限映射任務結束時合併小檔案，而且只會在任務的平均輸出大小小於 `hive.merge.smallfiles.avgsize` 設定時觸發合併。如果最終輸出路徑是在 HDFS 中，Amazon EMR Hive 也會有完全相同的行為。如果輸出路徑是在 Amazon S3 中，則會忽略 `hive.merge.smallfiles.avgsize` 參數。在此情況下，如果 `hive.merge.mapfiles` 設為 `true`，則合併任務一律會觸發。

### ACID 交易和 Amazon S3
<a name="emr-hive-acid"></a>

Amazon EMR 6.1.0 及更高版本支援 Hive ACID (不可部分完成性、一致性、隔離性、耐用性) 交易，因此它符合資料庫的 ACID 屬性。憑藉此功能，您可以在 Hive 受管資料表中使用 Amazon Simple Storage Service (Amazon S3) 中的資料來執行 INSERT、UPDATE、DELETE 和 MERGE 操作。

### Hive Live Long and Process (LLAP)
<a name="emr-hive-LLAP"></a>

Amazon EMR 5.0 版的 Hive 2.1.0 不支援預設 Apache Hive 2.0 版中新增的 [LLAP 功能](https://cwiki.apache.org/confluence/display/Hive/LLAP)。

Amazon EMR 6.0.0 及更高版本支援 Hive 的 Live Long and Process (LLAP) 功能。如需詳細資訊，請參閱[使用 Hive LLAP](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hive-llap.html)。

## Amazon EMR 發行版本 4.x 和 5.x 之間 Hive 的差異
<a name="emr-hive-diff"></a>

本章節涵蓋您將 Amazon EMR 4.x 版之 Hive 1.0.0 版 Hive 實作遷移至 Amazon EMR 5.x 版之 Hive 2.x 時應考量的差異。

### 運作的差異和考量
<a name="emr-hive-diffs-ops"></a>
+ **新增 [ACID (不可部分完成性、一致性、隔離性、耐用性) 交易的支援](https://cwiki.apache.org/confluence/display/Hive/Hive+Transactions)：**Amazon EMR 4.x 上的 Hive 1.0.0 與預設 Apache Hive 之間的這項差異已消除。
+ **已消除直接寫入 Amazon S3：**Amazon EMR 上的 Hive 1.0.0 與預設 Apache Hive 之間的這項差異已消除。Amazon EMR 5.x 版的 Hive 2.1.0 現在會建立、讀取和寫入存放於 Amazon S3 的暫時檔案。因此，您不再需要於叢集的本機 HDFS 檔案系統中建立暫存資料夾，做為讀取和寫入相同表格的解決方法。如果您使用版本控制的儲存貯體，則務必依下述管理這些暫存檔案。
+ **使用 Amazon S3 版本控制儲存貯體時管理暫時檔案：**當您執行 Hive 查詢，若所產生資料的目的地是 Amazon S3，則會建立許多暫時檔案和目錄。這是稍早所述的新行為。如果您使用版本控制的 S3 儲存貯體，這些暫時檔案會使 Amazon S3 變得雜亂，且未將它們刪除便會產生成本。請調整您的生命週期規則，讓 `/_tmp` 字首的資料在經過一段短時間後刪除，例如 5 天。如需詳細資訊，請參閱[指定生命週期組態](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-set-lifecycle-configuration-intro.html)。
+ **Log4j 已更新為 log4j 2：**如果您使用 log4j，則可能因為此升級而需要變更記錄組態。請參閱 [Apache log4j 2](http://logging.apache.org/log4j/2.x/) 了解詳細資訊。

### 效能的差異和考量
<a name="emr-hive-diffs-perf"></a>
+ **使用 Tez 的效能差異：**在 Amazon EMR 5.x 版中，Hive 的預設執行引擎是 Tez 而非 MapReduce。Tez 可為大多數工作流程提供更高的效能。
+ **具有許多分割區的表格：**產生大量動態分割區的查詢可能會失敗，而從具有許多分割區的表格選擇的查詢所需的執行時間可能比預期更久。例如，從 100,000 個分割區選擇可能要花 10 分鐘或更久。

## Amazon EMR 上 Hive 的其他功能
<a name="emr-hive-additional-features"></a>

Amazon EMR 使用支援 Hive 與其他 AWS 服務整合的新功能擴展 Hive，例如能夠讀取和寫入 Amazon Simple Storage Service (Amazon S3) 和 DynamoDB。

### Hive 中的變數
<a name="emr-hive-variables"></a>

 您可以使用貨幣符號和大括號在指令碼中包含變數。

```
add jar ${LIB}/jsonserde.jar
```

 您在命令列上使用 `-d` 參數將這些變數的值傳遞至 Hive，如以下範例所示：

```
-d LIB=s3://elasticmapreduce/samples/hive-ads/lib
```

 您也可以將值傳遞至執行 Hive 指令碼的步驟。

**使用主控台將變數值傳遞至 Hive 步驟**

1. 在 https：//[https://console.aws.amazon.com/emr](https://console.aws.amazon.com/emr/) 開啟 Amazon EMR 主控台。

1. 選擇 **Create Cluster** (建立叢集)。

1. 在 **Steps (步驟)** 區段，針對 **Add Step (新增步驟)**，從清單中選擇 **Hive Program (Hive 程式)** 和 **Configure and add (設定和新增)**。

1.  在 **Add Step (新增步驟)** 對話方塊中，使用下表做為指引指定參數，然後選擇 **Add (新增)**。    
[See the AWS documentation website for more details](http://docs.aws.amazon.com/zh_tw/emr/latest/ReleaseGuide/emr-hive-differences.html)

1. 選取必要的值，並選擇 **Create cluster (建立叢集)**。

**使用 將變數值傳遞至 Hive 步驟 AWS CLI**

若要使用 將變數值傳遞至 Hive 步驟 AWS CLI，請使用 `--steps` 參數並包含引數清單。
+ 
**注意**  
包含 Linux 行接續字元 (\\) 是為了提高可讀性。它們可以在 Linux 命令中移除或使用。對於 Windows，請將其移除或取代為插入符號 (^)。

  ```
  aws emr create-cluster --name "{{Test cluster}}" --release-label {{emr-7.13.0}} \
  --applications Name={{Hive}} Name={{Pig}} --use-default-roles --ec2-attributes KeyName={{myKey}} --instance-type {{m5.xlarge}} --instance-count {{3}} \
  --steps Type={{Hive}},Name="{{Hive Program}}",ActionOnFailure={{CONTINUE}},Args=[-f,{{s3://elasticmapreduce/samples/hive-ads/libs/response-time-stats.q}},-d,INPUT={{s3://elasticmapreduce/samples/hive-ads/tables}},-d,OUTPUT={{s3://amzn-s3-demo-bucket/hive-ads/output/}},-d,{{SAMPLE}}={{s3://elasticmapreduce/samples/hive-ads/}}]
  ```

  如需在 中使用 Amazon EMR 命令的詳細資訊 AWS CLI，請參閱 [https://docs.aws.amazon.com/cli/latest/reference/emr](https://docs.aws.amazon.com/cli/latest/reference/emr)。

**使用 Java 軟體開發套件將變數值傳遞至 Hive 步驟**
+ 以下範例示範如何使用軟體開發套件將變數傳遞至步驟。如需詳細資訊，請參閱《適用於 Java 的 AWS SDK API 參考》**中的[類別 StepFactory](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/elasticmapreduce/util/StepFactory.html)。

  ```
  StepFactory stepFactory = new StepFactory();
  
     StepConfig runHive = new StepConfig()
       .withName("Run Hive Script")
       .withActionOnFailure("TERMINATE_JOB_FLOW")
       .withHadoopJarStep(stepFactory.newRunHiveScriptStep(“s3://amzn-s3-demo-bucket/script.q”,
        Lists.newArrayList(“-d”,”LIB= s3://elasticmapreduce/samples/hive-ads/lib”));
  ```

### 納入部分 DynamoDB 結構描述的 Amazon EMR Hive 查詢
<a name="emr-hive-partial-schema"></a>

Amazon EMR Hive 可在查詢 DynamoDB 資料表時提供最大的彈性，讓您指定欄子集來篩選資料，而不需在查詢中包含所有資料欄。當您擁有疏鬆的資料庫結構描述，而想要依據少數幾欄篩選記錄 (例如篩選時間戳記) 時，這種部分結構描述查詢的技術就會非常有效。

 下列範例說明如何使用 Hive 查詢：
+ 建立 DynamoDB 資料表。
+ 選取 DynamoDB 中項目 (列) 的子集，並進一步縮小資料範圍至特定資料欄。
+ 將得到的資料複製到 Amazon S3。

```
DROP TABLE dynamodb; 
DROP TABLE s3;

CREATE EXTERNAL TABLE dynamodb(hashKey STRING, recordTimeStamp BIGINT, fullColumn map<String, String>)
    STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
    TBLPROPERTIES ( 
     "dynamodb.table.name" = "myTable",
     "dynamodb.throughput.read.percent" = ".1000", 
     "dynamodb.column.mapping" = "hashKey:HashKey,recordTimeStamp:RangeKey"); 

CREATE EXTERNAL TABLE s3(map<String, String>)
     ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
     LOCATION 's3://bucketname/path/subpath/';

INSERT OVERWRITE TABLE s3 SELECT item fullColumn FROM dynamodb WHERE recordTimeStamp < "2012-01-01";
```

下表顯示從 DynamoDB 選取任意項目組合的查詢語法。


| 查詢範例 | 結果描述 | 
| --- | --- | 
| SELECT \* FROM {{table\_name}}; | 從特定資料表選取所有項目 (列)，並包含所有欄中適用於這些項目的資料。 | 
| SELECT \* FROM {{table\_name}} WHERE {{field\_name}} ={{value}}; | 從特定資料表選取某些項目 (列)，並包含所有欄中適用於這些項目的資料。 | 
| SELECT {{column1\_name}}, {{column2\_name}}, {{column3\_name}} FROM {{table\_name}}; | 從特定資料表選取所有項目 (列)，並包含某些欄中適用於這些項目的資料。 | 
| SELECT {{column1\_name}}, {{column2\_name}}, {{column3\_name}} FROM {{table\_name}} WHERE {{field\_name}} ={{value}}; | 從特定資料表選取某些項目 (列)，並包含某些欄中適用於這些項目的資料。 | 

### 在不同 AWS 區域中的 DynamoDB 資料表之間複製資料
<a name="emr-hive-cross-region-ddb-copy"></a>

Amazon EMR Hive 會提供可對每個 DynamoDB 資料表設定的 `dynamodb.region` 屬性。當兩個資料表上的 `dynamodb.region` 設定不同時，您在資料表之間複製的任何資料都會自動出現在指定的區域之間。

 以下範例說明如何使用設定 `dynamodb.region` 屬性的 Hive 指令碼建立 DynamoDB 資料表：

**注意**  
個別資料表區域的屬性會覆寫全域 Hive 屬性。

```
CREATE EXTERNAL TABLE dynamodb(hashKey STRING, recordTimeStamp BIGINT, map<String, String> fullColumn)
    STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
    TBLPROPERTIES ( 
     "dynamodb.table.name" = "myTable",
     "dynamodb.region" = "eu-west-1", 
     "dynamodb.throughput.read.percent" = ".1000", 
     "dynamodb.column.mapping" = "hashKey:HashKey,recordTimeStamp:RangeKey");
```

### 設定每個資料表的 DynamoDB 輸送量值
<a name="emr-hive-set-ddb-throughput"></a>

Amazon EMR Hive 可讓您在資料表定義中設定個別資料表的 DynamoDB readThroughputPercent 和 writeThroughputPercent 設定。下列 Amazon EMR Hive 指令碼說明如何設定輸送量值。如需 DynamoDB 輸送量值的詳細資訊，請參閱[指定資料表的讀取和寫入需求](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithDDTables.html#ProvisionedThroughput)。

```
CREATE EXTERNAL TABLE dynamodb(hashKey STRING, recordTimeStamp BIGINT, map<String, String> fullColumn)
    STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
    TBLPROPERTIES ( 
     "dynamodb.table.name" = "myTable",
     "dynamodb.throughput.read.percent" = ".4",
     "dynamodb.throughput.write.percent" = "1.0",
     "dynamodb.column.mapping" = "hashKey:HashKey,recordTimeStamp:RangeKey");
```