

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon EMR 上的 Hive 的区别和注意事项
<a name="emr-hive-differences"></a>

## Amazon EMR 上的 Apache Hive 和 Apache Hive 之间的区别
<a name="emr-hive-apache-diff"></a>

本节介绍了 Hive on Amazon EMR 与上提供的 Hive 的默认版本之间的区别。[ http://svn.apache.org/viewvc/hive/branches/ ](http://svn.apache.org/viewvc/hive/branches/)

### 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 会在仅 map 作业结束时合并小文件，且仅在平均的作业输出大小低于 `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 属性。借助此功能，您可以使用 Amazon Simple Storage Service（Amazon S3）中的数据在 Hive 托管表中运行 INSERT、UPDATE、DELETE 和 MERGE 操作。

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

默认 Apache Hive 版本 2.0 中添加的 [LLAP 功能](https://cwiki.apache.org/confluence/display/Hive/LLAP)在 Amazon EMR 5.0 发行版上的 Hive 2.1.0 中不受支持。

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)。

## Hive 在 Amazon EMR 发行版 4.x 和 5.x 之间的不同
<a name="emr-hive-diff"></a>

本节介绍在将 Hive 实现从 Amazon EMR 4.x 发行版上的 Hive 1.0.0 版迁移到 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 受版本控制的存储桶时管理临时文件：**当您在生成数据的目的地是 Amazon S3 的环境中运行 Hive 查询时，会创建许多临时文件和目录。这是新行为，如上所述。如果您使用受版本控制的 S3 存储桶，那么不删除这些临时文件会使 Amazon S3 凌乱并产生费用。请调整生命周期规则，以便包含 `/_tmp` 前缀的数据在一个短周期 (例如，五天) 后被删除。有关更多信息，请参阅[指定生命周期配置](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 的性能差异：**在亚马逊 EMR 版本 5.x 中，Tez 是 Hive 的默认执行引擎，而不是. MapReduce Tez 为大多数工作流提供了改进的性能。
+ **具有多个分区的表：**生成大量动态分区的查询可能会失败，并且执行从具有多个分区的表中选择的查询可能需要比预期更长的时间。例如，从 100,000 个分区中进行选择可能需要 10 分钟或更长时间。

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

Amazon EMR 通过支持 Hive 与其他 AWS 服务集成的新功能扩展了 Hive，例如读取和写入亚马逊简单存储服务 (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. 打开 Amazon EMR 控制台（[https://console.aws.amazon.com/emr](https://console.aws.amazon.com/emr/)）。

1. 选择**创建集群**。

1. 在**步骤**部分中，对于 **Add Step (添加步骤)**，从列表中选择 **Hive Program (Hive 程序)**，然后选择 **Configure and add (配置并添加)**。

1.  在 **Add Step (添加步骤)** 对话框中，参考下表指定参数，然后选择**添加**。


<table>
<thead>
  <tr><th>字段</th><th>处理建议</th></tr>
</thead>
<tbody>
  <tr><td>脚本 S3 位置*</td><td>指定 Amazon S3 中脚本存储位置的 URI。该值必须采用{{BucketName}}/{{path}}/格式{{ScriptName}}。例如：<code>s3://elasticmapreduce/samples/hive-ads/libs/response-time-stats.q</code>。</td></tr>
  <tr><td>输入 S3 位置</td><td>指定 Amazon S3 中输入文件存储位置的 URI（可选）。该值必须采用{{BucketName}}/{{path}}/格式。如果指定完毕，则以名为“<code>INPUT</code>”的参数将其传递到 Hive 脚本。例如：<code>s3://elasticmapreduce/samples/hive-ads/tables/</code>。</td></tr>
  <tr><td>输出 S3 位置</td><td>指定您希望在 Amazon S3 中存储该输出的位置的 URI（可选）。该值必须采用{{BucketName}}/格式{{path}}。如果指定完毕，则以名为“<code>OUTPUT</code>”的参数将其传递到 Hive 脚本。例如：<code>s3://amzn-s3-demo-bucket/hive-ads/output/</code>。</td></tr>
  <tr><td>参数</td><td>输入要传递到 Hive 的参数列表（以空格分隔的字符串）。如果您在名为 ${SAMPLE} 的 Hive 脚本中定义了一个路径变量，如：<pre>CREATE EXTERNAL TABLE logs (requestBeginTime STRING, requestEndTime STRING, hostname STRING) PARTITIONED BY (dt STRING) \<br />ROW FORMAT serde 'com.amazon.elasticmapreduce.JsonSerde' <br />WITH SERDEPROPERTIES ( 'paths'='requestBeginTime, requestEndTime, hostname' ) LOCATION '${SAMPLE}/tables/impressions'; </pre>要传递该变量的值，请在<b>参数</b>窗口中键入以下内容：<br /><code>-d SAMPLE=s3://elasticmapreduce/samples/hive-ads/</code>.</td></tr>
  <tr><td>出现故障时的操作</td><td>这决定了集群为响应任何错误而执行的操作。此设置的可能值为：<ul><li> <b>Terminate cluster (终止集群)</b>：如果步骤失败，则终止集群。如果集群启用了终止保护和保持活动状态，则它不会终止。 </li><li> <b>Cancel and wait (取消并等待)</b>：如果步骤失败，则取消剩余步骤。如果集群启用了保持活动状态，则集群不会终止。 </li><li> <b>继续</b>：如果该步骤失败，则继续到下一个步骤。 </li></ul></td></tr>
</tbody>
</table>


1. 根据需要选择值，然后选择**创建集群**。

**要将变量值传递到 Hive 步骤，请使用 AWS CLI**

要使用将变量值传递到 Hive 步骤 AWS CLI，请使用`--steps`参数并包括参数列表。
+ 
**注意**  
为了便于读取，包含 Linux 行继续符（\\）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

  ```
  aws emr create-cluster --name "{{Test cluster}}" --release-label {{emr-7.14.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”));
  ```

### Amazon EMR Hive 查询可适应部分 DynamoDB 架构
<a name="emr-hive-partial-schema"></a>

在查询 DynamoDB 表时，Amazon EMR Hive 允许您指定一部分列作为数据筛选条件，而不要求您的查询包含所有列，因此可提供最大的灵活性。当采用稀疏数据库架构，并希望根据一些列来筛选记录 (例如根据时间戳筛选) 时，这种部分架构查询技术可以发挥作用。

 以下示例显示了如何使用 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 中选择任意项目组合的查询语法。


| 查询范例 | 结果描述 | 
| --- | --- | 
| 从{{table\_name}}; 中选择 \* | 从指定表选择所有项目 (行) 并包括这些项目对应的所有列的数据。 | 
| 从{{table\_name}}其中选择 \* {{field\_name}} ={{value}}; | 从指定表选择一些项目 (行) 并包括这些项目对应的所有列的数据。 | 
| {{column3\_name}}从{{column1\_name}}{{column2\_name}}、中选择{{table\_name}}； | 从指定表选择所有项目 (行) 并包括这些项目对应的一些列的数据。 | 
| {{column3\_name}}从{{table\_name}}其中选择 {{column1\_name}}{{column2\_name}}，，{{field\_name}}={{value}}; | 从指定表选择一些项目 (行) 并包括这些项目对应的一些列的数据。 | 

### 在不同的 DynamoDB 表之间复制数据 AWS Regions
<a name="emr-hive-cross-region-ddb-copy"></a>

Amazon EMR Hive 提供了可以为每个 DynamoDB 表设置的 `dynamodb.region` 属性。当两个表的 `dynamodb.region` 设置不同时，您在两个表之间执行的所有数据复制将自动在指定区域之间发生。

 以下示例显示了如何通过用于设置 `dynamodb.region` 属性的 Hive 脚本创建 DynamoDB 表：

**注意**  
Per-table 区域属性会覆盖全局 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 使您能够在表定义中以每个表为基础ThroughputPercent 设置 DynamoDB 读取ThroughputPercent 和写入设置。以下 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");
```