

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

# 改进 Hive 性能
<a name="emr-hive-s3-performance"></a>

Amazon EMR 提供一些功能，有助于优化使用 Hive 查询、读取和写入保存在 Amazon S3 中的数据的性能。

S3 Select 可通过将处理“向下推送”到 Amazon S3 来提高某些应用程序中 CSV 和 JSON 文件的查询性能。

EMRFS S3 优化的提交器是该[OutputCommitter](https://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapreduce/OutputCommitter.html)类的替代方案，它消除了列出和重命名操作，从而提高了使用 EMRFS 写入 Amazon S3 文件时的性能。

**Topics**
+ [启用 Hive EMRFS S3 优化提交程序](hive-optimized-committer.md)
+ [将 S3 Select 与 Hive 结合使用以提高查询性能](emr-hive-s3select.md)
+ [MSCK 优化](emr-msck-optimization.md)

# 启用 Hive EMRFS S3 优化提交程序
<a name="hive-optimized-committer"></a>

Hive EMRFS S3 优化提交器是 EMR Hive 在利用 EMRFS 时为插入查询写入文件所用的另一种方式。提交程序消除了在 Amazon S3 上执行的列表和重命名操作，并提高了应用程序性能。该功能可在 EMR 5.34 和 EMR 6.5 及更高版本中使用。

## 启用提交程序
<a name="enabling-hive-committer"></a>

如果您想启用 EMR Hive 以使用 `HiveEMRFSOptimizedCommitter` 提交数据作为所有 Hive 托管式表和外部表的默认值，请在 EMR 6.5.0 或 EMR 5.34.0 集群中使用以下 `hive-site` 配置。

```
[
   {
      "classification": "hive-site",
      "properties": {
         "hive.blobstore.use.output-committer": "true"
      }
   }
]
```

**注意**  
请勿在 `hive.exec.parallel` 设置为 `true` 时启动此功能。

## 限制
<a name="hive-committer-limitations"></a>

下面是适用于 标签的基本限制：
+ 不支持启用 Hive 自动合并小文件。即使启用了优化提交程序，也会使用默认的 Hive 提交逻辑。
+ 不支持 Hive ACID 表。即使启用了优化提交程序，也会使用默认的 Hive 提交逻辑。
+ 写入的文件的文件命名术语从 Hive 的 `<task_id>_<attempt_id>_<copy_n>` 更改为 `<task_id>_<attempt_id>_<copy_n>_<query_id>`。例如，文件命名为 

  `s3://warehouse/table/partition=1/000000_0` 将更改为 `s3://warehouse/table/partition=1/000000_0-hadoop_20210714130459_ba7c23ec-5695-4947-9d98-8a40ef759222-1`。此 `query_id` 是用户名、时间戳和 UUID 的组合。
+ 当自定义分区位于不同的文件系统（HDFS、S3）时，此功能将自动禁用。即使启用，也会使用默认的 Hive 提交逻辑。

# 将 S3 Select 与 Hive 结合使用以提高查询性能
<a name="emr-hive-s3select"></a>

**重要**  
不再向新客户提供 Amazon S3 Select。Amazon S3 Select 的现有客户可以像往常一样继续使用该功能。[了解详情](https://aws.amazon.com/blogs/storage/how-to-optimize-querying-your-data-in-amazon-s3/) 

对于 Amazon EMR 发行版 5.18.0 及更高版本，您可以将 [S3 Select](https://aws.amazon.com/blogs/aws/s3-glacier-select/) 与 Hive on Amazon EMR 搭配使用。S3 Select 可让应用程序仅从对象检索数据子集。对于 Amazon EMR，筛选要处理的大数据集的计算工作从集群“向下推送”到 Amazon S3，这可以在某些应用程序中提高性能和减少 Amazon EMR 与 Amazon S3 之间传输的数据量。

借助基于 CSV 和 JSON 文件的 Hive 表并在 Hive 会话期间将 `s3select.filter` 配置变量设置为 `true`，从而支持 S3 Select。有关更多信息以及示例，请参阅 [在代码中指定 S3 Select](#emr-hive-s3select-specify)。

## S3 Select 是否适合我的应用程序？
<a name="emr-hive-s3select-apps"></a>

建议您分别在使用和不使用 S3 Select 的情况下测试您的应用程序，以查看 S3 Select 是否适用于您的应用程序。

使用以下准则来确定您的应用程序是否为使用 S3 Select 的候选项：
+ 您的查询将筛选掉原始数据集的一半以上的数据。
+ 您的查询筛选谓词使用具有 Amazon S3 Select 支持的数据类型的列。有关更多信息，请参阅*《Amazon Simple Storage Service 用户指南》*中的[数据类型](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-glacier-select-sql-reference-data-types.html)。
+ 您在 Amazon S3 和 Amazon EMR 集群之间的网络连接具有良好的传输速度和可用带宽。Amazon S3 不压缩 HTTP 响应，因此响应大小可能会根据压缩的输入文件而增大。

## 注意事项和限制
<a name="emr-hive-s3select-considerations"></a>
+ 使用客户提供的加密密钥进行的 Amazon S3 服务器端加密（SSE-C）与客户端加密都不受支持。
+ 不支持 `AllowQuotedRecordDelimiters` 属性。如果指定该属性，则查询将失败。
+ 仅支持采用 UTF-8 格式的 CSV 和 JSON 文件。不支持多行 CSVs和 JSON。
+ 仅支持未压缩文件或 gzip、或 bzip2 文件。
+ 不支持最后一行中的注释字符。
+ 文件末尾的空行不会被处理。
+ Hive on Amazon EMR 支持 S3 Select 所支持的基元数据类型。有关更多信息，请参阅*《Amazon Simple Storage Service 用户指南》*中的[数据类型](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-glacier-select-sql-reference-data-types.html)。

## 在代码中指定 S3 Select
<a name="emr-hive-s3select-specify"></a>

要在 Hive 表中使用 S3 Select，请通过将 `com.amazonaws.emr.s3select.hive.S3SelectableTextInputFormat` 指定为 `INPUTFORMAT` 类名称以及使用 `TBLPROPERTIES` 子句为 `s3select.format` 属性指定一个值，来创建表。

默认情况下，S3 Select 在您运行查询时处于禁用状态。通过在您的 Hive 会话中将 `s3select.filter` 设置为 `true` 来启用 S3 Select，如下所示。下面的示例演示了如何在通过基础 CSV 和 JSON 文件创建表时指定 S3 Select，然后使用简单的 select 语句查询表。

**Example 基于 CSV 的 CREATE TABLE 语句**  

```
CREATE TABLE mys3selecttable (
col1 string,
col2 int,
col3 boolean
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS
INPUTFORMAT
  'com.amazonaws.emr.s3select.hive.S3SelectableTextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://path/to/mycsvfile/'
TBLPROPERTIES (
  "s3select.format" = "csv",
  "s3select.headerInfo" = "ignore"
);
```

**Example 基于 JSON 的 CREATE TABLE 语句**  

```
CREATE TABLE mys3selecttable (
col1 string,
col2 int,
col3 boolean
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS
INPUTFORMAT
  'com.amazonaws.emr.s3select.hive.S3SelectableTextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://path/to/json/'
TBLPROPERTIES (
  "s3select.format" = "json"
);
```

**Example SELECT TABLE 语句**  

```
SET s3select.filter=true;
SELECT * FROM mys3selecttable WHERE col2 > 10;
```

# MSCK 优化
<a name="emr-msck-optimization"></a>

Hive 在其元数据存储中存储每个表的分区列表。但是，当直接向文件系统添加分区或从文件系统中移除分区时，Hive 元数据存储不会意识到这些变化。对于直接添加到文件系统或从文件系统中移除的分区，[MSCK 命令](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-RecoverPartitions(MSCKREPAIRTABLE)) 会更新 Hive 元数据存储中的分区元数据。此命令的语法是：

```
MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];
```

Hive 将按如下方式实现此命令：

1. Hive 从元数据存储中检索表的所有分区。然后根据文件系统中不存在的分区路径列表，创建一个要从元数据存储中移除的分区列表。

1. Hive 收集文件系统中存在的分区路径，将其与元数据存储中的分区列表进行比较，然后生成需要添加到元数据存储的分区列表。

1. Hive 使用 `ADD`、`DROP` 或 `SYNC` 模式更新元数据存储。

**注意**  
如果元数据存储中有大量分区，检查文件系统中是否存在分区的步骤需要很长时间才能完成运行，因为必须对每个分区执行文件系统的 `exists` API 调用。

在 Amazon EMR 6.5.0 中，Hive 引入了一个名为 `hive.emr.optimize.msck.fs.check` 的标记。启用此标记后，它会让 Hive 检查上面第 2 步中所生成的文件系统分区路径列表中是否存在分区，而不是调用文件系统 API。在 Amazon EMR 6.8.0 中，Hive 默认启用了此优化，无需设置标记 `hive.emr.optimize.msck.fs.check`。