

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

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

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

[本节介绍亚马逊 EMR 上的 Hive 与 http://svn.apache 上的 Hive 默认版本之间的区别。 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 的性能差异：**在 Amazon EMR 5.x 版本中，Tez 是 Hive 的默认执行引擎，而不是。 MapReduceTez 为大多数工作流提供了改进的性能。
+ **具有多个分区的表：**生成大量动态分区的查询可能会失败，并且执行从具有多个分区的表中选择的查询可能需要比预期更长的时间。例如，从 100,000 个分区中进行选择可能需要 10 分钟或更长时间。

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

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

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

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

1.  在 **Add Step (添加步骤)** 对话框中，参考下表指定参数，然后选择**添加**。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/emr/latest/ReleaseGuide/emr-hive-differences.html)

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

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

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

  ```
  aws emr create-cluster --name "Test cluster" --release-label emr-7.12.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 中选择任意项目组合的查询语法。


| 查询范例 | 结果描述 | 
| --- | --- | 
| 从 “\$1” 中选择table\$1name； | 从指定表选择所有项目 (行) 并包括这些项目对应的所有列的数据。 | 
| 从table\$1name哪里选择 \$1 field\$1name =value; | 从指定表选择一些项目 (行) 并包括这些项目对应的所有列的数据。 | 
| 选择column1\$1name、column2\$1name、column3\$1name来自table\$1name； | 从指定表选择所有项目 (行) 并包括这些项目对应的一些列的数据。 | 
| 从 field\$1name =value; column3\$1name 中table\$1name选择column1\$1namecolumn2\$1name、、 | 从指定表选择一些项目 (行) 并包括这些项目对应的一些列的数据。 | 

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

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

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

**注意**  
每个表的 region 属性会覆盖全局 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");
```