

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

# Apache Spark
<a name="emr-spark"></a>

[Apache Spark](https://aws.amazon.com/emr/features/spark/) 是一个分布式处理框架和编程模型，可帮助您使用 Amazon EMR 集群进行机器学习、流处理或图形分析。Spark 与 Apache Hadoop 类似，也是一款常用于大数据工作负载的开源、分布式处理系统。但是，Spark 与 Hadoop MapReduce 有几个显著的区别。Spark 拥有经过优化的有向无环图 (DAG) 执行引擎并会积极地在内存中缓存数据，这可提高性能，尤其是对于某些算法和交互式查询。

Spark 内在支持使用 Scala、Python 和 Java 编写的应用程序。它还包括几个紧密集成的库，用于 SQL ([Spark](https://spark.apache.org/sql/))、机器学习 ([MLlib](https://spark.apache.org/mllib/))、流处理（[Spark](https://spark.apache.org/streaming/) 流）和图形处理（[GraphX](https://spark.apache.org/graphx/)）。这些工具可让您更轻松地在各种使用案例中充分发挥 Spark 框架的优势。

您可以在 Amazon EMR 集群上与其他 Hadoop 应用程序一同安装 Spark，它还能借助 Amazon EMR 文件系统（EMRFS）直接访问 Amazon S3 中的数据。Hive 还与 Spark 集成，因此你可以使用 HiveContext 对象通过 Spark 运行 Hive 脚本。Hive 上下文作为 `sqlContext` 包含在 Spark Shell 中。

有关使用 Spark 设置 EMR 集群和分析示例数据集的示例教程，请参阅新闻博客上的[教程：Amazon EMR 入门](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-gs.html)。 AWS 

你可以使用 Apache Spark 故障排除代理对 EC2 上的 EMR 和 EMR Serverless 上的 Apache Spark 应用程序进行故障排除。要了解更多信息，请参阅[什么是 Amazon EMR 的 Apache Spark 故障排除代理](spark-troubleshoot.md)。

**重要**  
Apache Spark 版本 2.3.1（从 Amazon EMR 发行版 5.16.0 开始提供）解决了 [CVE-2018-8024](https://nvd.nist.gov/vuln/detail/CVE-2018-8024) 和 [CVE-2018-1334](https://nvd.nist.gov/vuln/detail/CVE-2018-1334) 问题。建议您将 Spark 的早期版本迁移到 Spark 2.3.1 版本或更高版本。

下表列出了 Amazon EMR 7.x 系列的最新发行版附带的 Spark 的版本，以及 Amazon EMR 随 Spark 一起安装的组件。

有关此版本中与 Spark 一起安装的组件的版本，请参阅 [7.12.0 版本的组件](emr-7120-release.md)版本。


**emr-7.12.0 的 Spark 版本信息**  

| Amazon EMR 发行版标签 | Spark 版本 | 随 Spark 安装的组件 | 
| --- | --- | --- | 
| emr-7.12.0 | Spark 3.5.6-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-hdfs-zkfc, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 

下表列出了 Amazon EMR 6.x 系列的最新发行版附带的 Spark 的版本，以及 Amazon EMR 随 Spark 一起安装的组件。

有关此发行版中随 Spark 安装的组件版本，请参阅[发行版 6.15.0 组件版本](emr-6150-release.md)。


**emr-6.15.0 的 Spark 版本信息**  

| Amazon EMR 发行版标签 | Spark 版本 | 随 Spark 安装的组件 | 
| --- | --- | --- | 
| emr-6.15.0 | Spark 3.4.1-amzn-2 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 

**注意**  
Amazon EMR 发行版 6.8.0 随附 Apache Spar 3.3.0。此 Spark 发行版使用 Apache Log4j 2 和 `log4j2.properties` 文件，在 Spark 进程中配置 Log4j。如果您在集群中使用 Spark 或使用自定义配置参数创建 EMR 集群，并且希望升级到 Amazon EMR 发行版 6.8.0，则必须迁移到新的 `spark-log4j2` 配置分类和 Apache Log4j 2 的密钥格式。有关更多信息，请参阅 [从 Apache Log4j 1.x 迁移到 Log4j 2.x](emr-spark-configure.md#spark-migrate-logj42)。

下表列出了 Amazon EMR 5.x 系列的最新发行版附带的 Spark 的版本，以及 Amazon EMR 随 Spark 一起安装的组件。

有关此发行版中随 Spark 安装的组件版本，请参阅[发行版 5.36.2 组件版本](emr-5362-release.md)。


**emr-5.36.2 的 Spark 版本信息**  

| Amazon EMR 发行版标签 | Spark 版本 | 随 Spark 安装的组件 | 
| --- | --- | --- | 
| emr-5.36.2 | Spark 2.4.8-amzn-2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 

**Topics**
+ [使用 Apache Spark 创建集群](emr-spark-launch.md)
+ [在 Amazon EMR 6.x 上使用 Docker 运行 Spark 应用程序](emr-spark-docker.md)
+ [在亚马逊 EMR 上使用 AWS Glue 数据目录和 Spark](emr-spark-glue.md)
+ [在亚马逊 EMR 上使用 Spark 在 AWS Glue 数据目录中使用多目录层次结构](emr-multi-catalog.md)
+ [配置 Spark](emr-spark-configure.md)
+ [什么是 Amazon EMR 的 Apache Spark 故障排除代理](spark-troubleshoot.md)
+ [优化 Spark 性能](emr-spark-performance.md)
+ [Spark 结果片段缓存](emr-spark-fragment-result-caching.md)
+ [使用 Nvidia RAPIDS Accelerator for Apache Spark](emr-spark-rapids.md)
+ [访问 Spark Shell](emr-spark-shell.md)
+ [使用 Amazon SageMaker Spark 进行机器学习](emr-spark-sagemaker.md)
+ [编写 Spark 应用程序](emr-spark-application.md)
+ [使用 Amazon S3 提高 Spark 性能](emr-spark-s3-performance.md)
+ [添加 Spark 步骤](emr-spark-submit-step.md)
+ [查看 Spark 应用程序历史记录](emr-spark-application-history.md)
+ [访问 Spark 网站 UIs](emr-spark-webui.md)
+ [使用 Spark 结构化流 Amazon Kinesis Data Streams 连接器](emr-spark-structured-streaming-kinesis.md)
+ [将适用于 Apache Spark 的 Amazon Redshift 集成与 Amazon EMR 结合使用](emr-spark-redshift.md)
+ [Spark 发行历史记录](Spark-release-history.md)
+ [在 Amazon EMR 中使用物化视图](emr-spark-materialized-views.md)

# 使用 Apache Spark 创建集群
<a name="emr-spark-launch"></a>

以下程序在 Amazon EMR 控制台中使用**快速选项** 创建一个安装了 [Spark](https://aws.amazon.com/big-data/what-is-spark/) 的集群。

作为替代，您可以使用 **Advanced Options (高级选项)** 进一步自定义您的集群设置，或是提交步骤以编程方式安装应用程序，然后执行自定义应用程序。利用这些集群创建选项之一，您可以选择使用 AWS Glue 作为您的 Spark SQL 元存储。请参阅[在亚马逊 EMR 上使用 AWS Glue 数据目录和 Spark](emr-spark-glue.md)了解更多信息。

**启动安装了 Spark 的集群**

1. [在 /emr 上打开亚马逊 EMR 控制台。https://console.aws.amazon.com](https://console.aws.amazon.com/emr/)

1. 选择 **Create cluster (创建集群)** 以使用 **Quick Options (快速选项)**。

1. 输入 **Cluster name (集群名称)**。集群名称不能包含字符 <、>、\$1、\$1 或 `（反引号）。

1.  在 **Software Configuration (软件配置)** 中，选择 **Release (发行版)** 选项。

1.  在 **Applications (应用程序)** 中，选择 **Spark** 应用程序捆绑包。

1.  根据需要选择其它选项，然后选择 **Create cluster (创建集群)**。
**注意**  
要在创建集群时配置 Spark，请参阅[配置 Spark](emr-spark-configure.md)。

**要启动安装了 Spark 的集群，请使用 AWS CLI**
+ 使用下面的命令创建集群。

  ```
  aws emr create-cluster --name "Spark cluster" --release-label emr-7.12.0 --applications Name=Spark \
  --ec2-attributes KeyName=myKey --instance-type m5.xlarge --instance-count 3 --use-default-roles
  ```

**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

**使用 SDK for Java 启动安装了 Spark 的集群**

通过 `SupportedProductConfig` 中使用的 `RunJobFlowRequest` 指定 Spark 作为应用程序。
+ 下面的实例显示如何通过 Java 使用 Spark 创建集群：

  ```
  import com.amazonaws.AmazonClientException;
  import com.amazonaws.auth.AWSCredentials;
  import com.amazonaws.auth.AWSStaticCredentialsProvider;
  import com.amazonaws.auth.profile.ProfileCredentialsProvider;
  import com.amazonaws.services.elasticmapreduce.AmazonElasticMapReduce;
  import com.amazonaws.services.elasticmapreduce.AmazonElasticMapReduceClientBuilder;
  import com.amazonaws.services.elasticmapreduce.model.*;
  import com.amazonaws.services.elasticmapreduce.util.StepFactory;
  
  public class Main {
  
          public static void main(String[] args) {
                  AWSCredentials credentials_profile = null;
                  try {
                          credentials_profile = new ProfileCredentialsProvider("default").getCredentials();
                  } catch (Exception e) {
                          throw new AmazonClientException(
                                          "Cannot load credentials from .aws/credentials file. " +
                                                          "Make sure that the credentials file exists and the profile name is specified within it.",
                                          e);
                  }
  
                  AmazonElasticMapReduce emr = AmazonElasticMapReduceClientBuilder.standard()
                                  .withCredentials(new AWSStaticCredentialsProvider(credentials_profile))
                                  .withRegion(Regions.US_WEST_1)
                                  .build();
  
                  // create a step to enable debugging in the AWS Management Console
                  StepFactory stepFactory = new StepFactory();
                  StepConfig enabledebugging = new StepConfig()
                                  .withName("Enable debugging")
                                  .withActionOnFailure("TERMINATE_JOB_FLOW")
                                  .withHadoopJarStep(stepFactory.newEnableDebuggingStep());
  
                  Application spark = new Application().withName("Spark");
  
                  RunJobFlowRequest request = new RunJobFlowRequest()
                                  .withName("Spark Cluster")
                                  .withReleaseLabel("emr-5.20.0")
                                  .withSteps(enabledebugging)
                                  .withApplications(spark)
                                  .withLogUri("s3://path/to/my/logs/")
                                  .withServiceRole("EMR_DefaultRole")
                                  .withJobFlowRole("EMR_EC2_DefaultRole")
                                  .withInstances(new JobFlowInstancesConfig()
                                                  .withEc2SubnetId("subnet-12ab3c45")
                                                  .withEc2KeyName("myEc2Key")
                                                  .withInstanceCount(3)
                                                  .withKeepJobFlowAliveWhenNoSteps(true)
                                                  .withMasterInstanceType("m4.large")
                                                  .withSlaveInstanceType("m4.large"));
                  RunJobFlowResult result = emr.runJobFlow(request);
                  System.out.println("The cluster ID is " + result.toString());
          }
  }
  ```

# 在 Amazon EMR 6.x 上使用 Docker 运行 Spark 应用程序
<a name="emr-spark-docker"></a>

**注意**  
所描述的过程仅适用于 Amazon EMR 6.x 版本。

借助 Amazon EMR 6.0.0，Spark 应用程序可以使用 Docker 容器来定义其库依赖项，而不是在集群中的单个 Amazon EC2 实例上安装依赖项。要使用 Docker 运行 Spark，您必须首先配置 Docker 注册表，并在提交 Spark 应用程序时定义其他参数。有关更多信息，请参阅[配置 Docker 集成](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-docker.html)。

提交应用程序时，YARN 调用 Docker 来拉取指定的 Docker 映像并在 Docker 容器内运行 Spark 应用程序。这让您可以轻松地定义和隔离依赖项。它可以通过执行任务所需的库来缩短在 Amazon EMR 集群中引导启动或准备实例的时间。

## 利用 Docker 运行 Spark 时的注意事项
<a name="emr-spark-docker-considerations"></a>

使用 Docker 运行 Spark 时，请确保满足以下先决条件：
+ `docker` 程序包和 CLI 仅安装在核心节点和任务节点上。
+ 在 Amazon EMR 6.1.0 及更高版本中，您也可以使用以下命令在主节点安装 Docker。
  + 

    ```
    sudo yum install -y docker
    sudo systemctl start docker
    ```
+ `spark-submit` 命令应始终从 Amazon EMR 集群上的主实例运行。
+ 用于解析 Docker 映像的 Docker 注册表必须使用带有 `container-executor` 分类键的分类 API 来定义，以便在启动集群时定义其他参数：
  + `docker.trusted.registries`
  + `docker.privileged-containers.registries`
+ 要在 Docker 容器中执行 Spark 应用程序，需要以下配置选项：
  + `YARN_CONTAINER_RUNTIME_TYPE=docker`
  + `YARN_CONTAINER_RUNTIME_DOCKER_IMAGE={DOCKER_IMAGE_NAME}`
+ 使用 Amazon ECR 检索 Docker 镜像时，必须将集群配置为对自身进行身份验证。为此，您必须使用以下配置选项：
  + YARN\$1CONTAINER\$1RUNTIME\$1DOCKER\$1CLIENT\$1CONFIG=\$1DOCKER\$1CLIENT\$1CONFIG\$1PATH\$1ON\$1HDFS\$1
+ 在 Amazon EMR 6.1.0 及更高版本中，当自用 ECR 自动身份验证时，您不需要使用列出的命令 `YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG={DOCKER_CLIENT_CONFIG_PATH_ON_HDFS}`。
+ 与 Spark 一起使用的任何 Docker 映像都必须在 Docker 映像中安装了 Java。

有关先决条件的更多信息，请参阅[配置 Docker 集成](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-docker.html)。

## 创建 Docker 镜像
<a name="emr-spark-docker-image"></a>

Docker 映像是使用 Dockerfile 创建的，该文件定义了要包含在映像中的程序包和配置。以下两个 Dockerfile 使用和 PySpark SparkR 的示例。

**PySpark Dockerfile**

使用此 Dockerfile 创建的 Docker 镜像包括 Python 3 和 Python 软件包 NumPy 。此 Dockerfile 使用 Amazon Linux 2 和 Amazon Corretto JDK 8。

```
FROM amazoncorretto:8

RUN yum -y update
RUN yum -y install yum-utils
RUN yum -y groupinstall development

RUN yum list python3*
RUN yum -y install python3 python3-dev python3-pip python3-virtualenv

RUN python -V
RUN python3 -V

ENV PYSPARK_DRIVER_PYTHON python3
ENV PYSPARK_PYTHON python3

RUN pip3 install --upgrade pip
RUN pip3 install numpy pandas

RUN python3 -c "import numpy as np"
```

**SparkR Dockerfile**

从该 Dockerfile 创建的 Docker 映像包括 R 和 randomForest CRAN 程序包。此 Dockerfile 包含 Amazon Linux 2 和 Amazon Corretto JDK 8。

```
FROM amazoncorretto:8

RUN java -version

RUN yum -y update
RUN amazon-linux-extras install R4

RUN yum -y install curl hostname

#setup R configs
RUN echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile

RUN Rscript -e "install.packages('randomForest')"
```

有关 Dockerfile 语法的更多信息，请参阅 [Dockerfile 参考文档](https://docs.docker.com/engine/reference/builder/)。

## 使用来自 Amazon ECR 的 Docker 镜像
<a name="emr-spark-docker-ECR"></a>

Amazon Elastic Container Registry（Amazon ECR）是一个完全托管式 Docker 容器注册表，可让开发人员轻松地存储、管理和部署 Docker 容器镜像。使用 Amazon ECR 时，必须将集群配置为信任您的 ECR 实例，并且必须配置身份验证，以便集群使用来自 Amazon ECR 的 Docker 镜像。有关更多信息，请参阅[配置 YARN 以访问 Amazon ECR](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-docker.html#emr-docker-ECR)。

要确保 Amazon EMR 主机可以访问存储在 Amazon ECR 中的镜像，集群必须具有通过 `AmazonEC2ContainerRegistryReadOnly` 策略授予的与实例配置文件关联的权限。有关更多信息，请参阅[`AmazonEC2ContainerRegistryReadOnly`策略](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html#AmazonEC2ContainerRegistryReadOnly)。

在此示例中，必须使用以下附加配置创建集群，以确保 Amazon ECR 注册表受信任。将*123456789123.dkr.ecr.us-east-1.amazonaws.com*终端节点替换为您的 Amazon ECR 终端节点。

```
[
  {
    "Classification": "container-executor",
    "Configurations": [
      {
        "Classification": "docker",
        "Properties": {
          "docker.privileged-containers.registries": "local,centos,123456789123.dkr.ecr.us-east-1.amazonaws.com",
          "docker.trusted.registries": "local,centos,123456789123.dkr.ecr.us-east-1.amazonaws.com"
        }
      }
    ],
    "Properties": {}
  }
]
```

** PySpark 与 Amazon ECR 一起使用**

以下示例使用 PySpark Dockerfile，该文件将被标记并上传到 Amazon ECR。上传 Dockerfile 后，你可以运行 PySpark 任务并引用来自亚马逊 ECR 的 Docker 镜像。

启动集群后，使用 SSH 连接到核心节点，然后运行以下命令从 Dock PySpark erfile 示例中构建本地 Docker 镜像。

首先，创建一个目录和一个 Dockerfile。

```
mkdir pyspark
vi pyspark/Dockerfile
```

粘贴 PySpark Dockerfile 的内容并运行以下命令来构建 Docker 镜像。

```
sudo docker build -t local/pyspark-example pyspark/
```

为示例创建 `emr-docker-examples` ECR 存储库。

```
aws ecr create-repository --repository-name emr-docker-examples
```

标记本地构建的映像并将其上传到 ECR，*123456789123.dkr.ecr.us-east-1.amazonaws.com*替换为您的 ECR 端点。

```
sudo docker tag local/pyspark-example 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
sudo docker push 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
```

使用 SSH 连接到主节点并准备文件名为 `main.py` 的 Python 脚本。将以下内容粘贴到 `main.py` 文件中并保存它。

```
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("docker-numpy").getOrCreate()
sc = spark.sparkContext

import numpy as np
a = np.arange(15).reshape(3, 5)
print(a)
```

要在 Amazon EMR 6.0.0 上提交作业，请引用 Docker 映像的名称。定义其他配置参数，以确保作业执行使用 Docker 作为运行时。使用 Amazon ECR 时，`YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG` 必须引用 `config.json` 文件，其中包含用于对 Amazon ECR 进行身份验证的凭证。

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
DOCKER_CLIENT_CONFIG=hdfs:///user/hadoop/config.json
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
--num-executors 2 \
main.py -v
```

要在 Amazon EMR 6.1.0 及更高版本中提交作业，请引用 Docker 映像的名称。启用 ECR 自动身份验证后，运行以下命令。

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--num-executors 2 \
main.py -v
```

任务完成后，记下 YARN 应用程序 ID，然后使用以下命令获取 PySpark 任务的输出。

```
yarn logs --applicationId application_id | grep -C2 '\[\['
LogLength:55
LogContents:
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
```

**将 SparkR 与 Amazon ECR 结合使用**

以下示例使用 SparkR Dockerfile，该文件将被标记并上传到 ECR。上载此 Dockerfile 之后，您可以运行 SparkR 任务并从 Amazon ECR 中引用 Docker 镜像。

启动集群后，使用 SSH 连接到核心节点，并运行以下命令从 SparkR Dockerfile 示例构建本地 Docker 映像。

首先，创建一个目录和该 Dockerfile。

```
mkdir sparkr
vi sparkr/Dockerfile
```

粘贴 SparkR Dockerfile 的内容并运行以下命令来构建 Docker 映像。

```
sudo docker build -t local/sparkr-example sparkr/
```

标记本地构建的映像并将其上传到 Amazon ECR，替换*123456789123.dkr.ecr.us-east-1.amazonaws.com*为您的 Amazon ECR 终端节点。

```
sudo docker tag local/sparkr-example 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
sudo docker push 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
```

使用 SSH 连接到主节点并准备名为 `sparkR.R` 的 R 脚本。将以下内容粘贴到 `sparkR.R` 文件中。

```
library(SparkR)
sparkR.session(appName = "R with Spark example", sparkConfig = list(spark.some.config.option = "some-value"))

sqlContext <- sparkRSQL.init(spark.sparkContext)
library(randomForest)
# check release notes of randomForest
rfNews()

sparkR.session.stop()
```

要在 Amazon EMR 6.0.0 上提交作业，请引用 Docker 映像的名称。定义其他配置参数，以确保作业执行使用 Docker 作为运行时。使用 Amazon ECR 时，`YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG` 必须引用 `config.json` 文件，其中包含用于对 ECR 进行身份验证的凭证。

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
DOCKER_CLIENT_CONFIG=hdfs:///user/hadoop/config.json
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG=$DOCKER_CLIENT_CONFIG \
sparkR.R
```

要在 Amazon EMR 6.1.0 及更高版本中提交作业，请引用 Docker 映像的名称。启用 ECR 自动身份验证后，运行以下命令。

```
DOCKER_IMAGE_NAME=123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:sparkr-example
spark-submit --master yarn \
--deploy-mode cluster \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE=docker \
--conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$DOCKER_IMAGE_NAME \
sparkR.R
```

作业完成后，记下 YARN 应用程序 ID，并使用以下命令获取 SparkR 作业的输出。此示例包括测试，以确保 randomForest 库、已安装的版本和发布说明可用。

```
yarn logs --applicationId application_id | grep -B4 -A10 "Type rfNews"
randomForest 4.6-14
Type rfNews() to see new features/changes/bug fixes.
Wishlist (formerly TODO):

* Implement the new scheme of handling classwt in classification.

* Use more compact storage of proximity matrix.

* Allow case weights by using the weights in sampling?

========================================================================
Changes in 4.6-14:
```

# 在亚马逊 EMR 上使用 AWS Glue 数据目录和 Spark
<a name="emr-spark-glue"></a>

使用 Amazon EMR 版本 5.8.0 或更高版本，您可以将 Spark 配置为使用 Glue 数据目录作为其 Apac AWS he Hive 元数据库。如果您需要由不同集群、服务、应用程序或账户共享的永久 Hive 元数据仓或 Hive 元数据仓，我们建议您使用此配置。 AWS 

使用 Amazon EMR 版本 6.5.0 或更高版本，您可以将 Spark 配置为在 Apache Iceberg 中使用 AWS Glue 数据目录。

使用 Amazon EMR 版本 7.5.0 或更高版本，您可以将 Spark 配置为使用 G AWS lue 数据目录作为其 Iceberg REST 目录。

AWS Glue 是一项完全托管的提取、转换和加载 (ETL) 服务，它使对数据进行分类、清理、丰富数据并在各种数据存储之间可靠地移动数据变得简单且经济高效。 AWS Glue 数据目录提供了一个跨各种数据源和数据格式的统一元数据存储库，与亚马逊 EMR 以及亚马逊 RDS、Amazon Redshift、Redshift Spectrum、Athena 以及任何与 Apache Hive 元数据仓兼容的应用程序集成。 AWS Glue 爬网程序可以自动从 Amazon S3 中的源数据推断出架构，并将相关的元数据存储在数据目录中。有关数据目录的更多信息，请参阅 [AWS Glue *开发者指南中的填充 G AWS l* ue 数据目录](https://docs.aws.amazon.com/glue/latest/dg/populate-data-catalog.html)。

Glue 需单独收 AWS 费。在数据目录中存储和访问元数据有月费率，Gl AWS ue ETL 作业和爬虫运行时按小时费率收费，每个预配置的开发端点按每分钟计费。数据目录让您最多可免费存储一百万个对象。如果您存储一百万个以上的对象，将需要为超过一百万的每 100,000 个对象支付 1 美元。数据目录中的对象为表、分区或数据库。有关更多信息，请参阅 [Glue 定价](https://aws.amazon.com/glue/pricing)。

**重要**  
如果您在 2017 年 8 月 14 日之前使用 Amazon Athena 或 Amazon Redshift Spectrum 创建了表，则数据库和表将存储在雅典娜管理的目录中，该目录与 Glue 数据目录是分开的。 AWS 要将 Amazon EMR 与这些表集成，您必须升级到 Glue 数据 AWS 目录。有关更多信息，请参阅*亚马逊 Athena AWS 用户指南中的升级到 Glue* [数据目录](https://docs.aws.amazon.com/athena/latest/ug/glue-upgrade.html)。

## 将 AWS Glue 数据目录指定为 Apache Hive 元数据仓
<a name="emr-spark-glue-configure"></a>

您可以使用 AWS 管理控制台、 AWS CLI或 Amazon EMR API 将 AWS Glue 数据目录指定为元数据库。在使用 CLI 或 API 时，您可以使用 Spark 的配置分类指定数据目录。此外，在 Amazon EMR 5.16.0 及更高版本中，您可以使用配置分类在不同的目录中指定数据目录。 AWS 账户在使用控制台时，您可以使用 **Advanced Options (高级选项)** 或 **Quick Options (快速选项)** 指定数据目录。

**注意**  
齐柏林飞艇还提供使用 AWS Glue Data Catalog 的选项，因为齐柏林飞艇安装了 Spark 组件。

------
#### [ Console ]

**使用新控制台 AWS 将 Glue 数据目录指定为 Apache Hive 元数据仓库**

1. [登录 AWS 管理控制台，然后在 /emr 上打开亚马逊 EMR 控制台。https://console.aws.amazon.com](https://console.aws.amazon.com/emr)

1. 在左侧导航窗格中的 **Amazon EMR on EC2** 下，选择**集群**，然后选择**创建集群**。

1. 在 **Application bundle**（应用程序包）下，选择 **Spark** 或 **Custom**（自定义）。如果您自定义集群，请确保选择 Zeppelin 或 Spark 作为应用程序之一。

1. 在 **AWS Glue Data Catalog s设置**下，选择**用于 Spark 表元数据**复选框。

1. 选择适用于集群的任何其他选项。

1. 要启动集群，选择 **Create cluster**（创建集群）。

------
#### [ AWS CLI ]

**要将 Glue AWS 数据目录指定为 Apache Hive 元数据仓库 AWS CLI**

有关使用 AWS CLI 和 Amazon EMR API 指定配置分类的更多信息，请参阅。[配置应用程序](emr-configure-apps.md)
+ 使用 `spark-hive-site` 分类指定 `hive.metastore.client.factory.class` 的值，如下例所示：

  ```
  [
    {
      "Classification": "spark-hive-site",
      "Properties": {
        "hive.metastore.client.factory.class": "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory"
      }
    }
  ]
  ```

  要在其他 AWS 账户中指定数据目录，请添加`hive.metastore.glue.catalogid`属性，如以下示例所示。将 `acct-id` 替换为数据目录的 AWS 账户。

  ```
  [
    {
      "Classification": "spark-hive-site",
      "Properties": {
        "hive.metastore.client.factory.class": "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory",
        "hive.metastore.glue.catalogid": "acct-id"
      }
    }
  ]
  ```

------

## 将 AWS Glue 数据目录指定为 Apache 冰山目录
<a name="emr-spark-glue-configure-iceberg"></a>

你可以使用、、或 Amazon EMR API 或 Spark 会话运行时配置将 AWS Glue 数据目录指定为 Apache Iceberg 目录实现 AWS CLI或 Apache Iceberg REST 目录终端节点。 AWS 管理控制台在使用 CLI 或 API 时，您可以使用 Spark 的配置分类指定数据目录。有关更多详细信息，请参阅[将 AWS Glue 数据目录指定为 Apache Iceberg](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-spark-glue.html#emr-spark-glue-configure-iceberg) 目录。

## IAM 权限
<a name="emr-hive-glue-permissions"></a>

集群的 EC2 实例配置文件必须具有 AWS Glue 操作的 IAM 权限。此外，如果您为 AWS Glue Data Catalog 对象启用加密，则还必须允许该角色加密、解密和生成 AWS KMS key 用于加密的对象。

### AWS Glue 操作的权限
<a name="emr-hive-glue-permissions-actions"></a>

如果使用适用于 Amazon EMR 默认的 EC2 实例配置文件，则无需执行任何操作。附加到的`AmazonElasticMapReduceforEC2Role`托管策略`EMR_EC2_DefaultRole`允许执行所有必要的 AWS Glue 操作。但是，如果您指定自定义 EC2 实例配置文件和权限，则必须配置相应的 AWS Glue 操作。使用 `AmazonElasticMapReduceforEC2Role` 托管策略作为起点。如需了解更多信息，请参阅*《Amazon EMR 管理指南》*中的[集群 EC2 实例的服务角色（EC2 实例配置文件）](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html)。

### 加密和解密 AWS Glue 数据目录的权限
<a name="emr-hive-glue-permissions-encrypt"></a>

您的实例配置文件需要使用密钥加密和解密数据的权限。如果以下语句适用，您*不必*配置这些权限：
+ 您可以使用 Glue 的 AWS 托管密钥为 Glue 数据目录对象启用加密。 AWS 
+ 您使用的集群与 Gl AWS ue 数据目录 AWS 账户 相同。

否则，您必须将以下语句添加到附加到 EC2 实例配置文件的权限策略。

有关 AWS Glue 数据目录加密的更多信息，请参阅 Glu [e *开发者指南中的AWS 加密*数据目录](https://docs.aws.amazon.com/glue/latest/dg/encrypt-glue-data-catalog.html)。

### 基于资源的权限
<a name="emr-hive-glue-permissions-resource"></a>

如果您在 Amazon EMR 中将 AWS Glue 与 Hive、Spark 或 Presto 结合使用， AWS Glue 支持基于资源的策略来控制对数据目录资源的访问。这些资源包括数据库、表、连接和用户定义的函数。有关更多信息，请参阅《AWS Glue 开发人员指南》**中的 [AWS Glue 资源策略](https://docs.aws.amazon.com/glue/latest/dg/glue-resource-policies.html)。

使用基于资源的策略限制从 Amazon EMR 中访问 AWS Glue 时，您在权限策略中指定的委托人必须是与创建集群时指定的 EC2 实例配置文件关联的角色 ARN。例如，对于附加到目录的基于资源的策略，您可以使用以下示例所示的格式为集群 EC2 实例*EMR\$1EC2\$1DefaultRole*的默认服务角色指定角色 ARN，如下所示：`Principal`

```
arn:aws:iam::acct-id:role/EMR_EC2_DefaultRole
```

*acct-id*可以与 Glue 账 AWS 号 ID 不同。这允许从不同账户中的 EMR 集群进行访问。您可以指定多个委托人，且每个委托人都可以来自不同的账户。

## 使用 AWS Glue 数据目录时的注意事项
<a name="emr-hive-glue-considerations-hive"></a>

使用 AWS Glue 数据目录作为带有 Spark 的 Apache Hive 元数据仓时，请考虑以下事项：
+ 当您创建表时，具有没有位置 URI 的默认数据库会导致失败。作为解决方法，请在您使用 `LOCATION` 时使用 `s3://amzn-s3-demo-bucket1` 子句指定一个存储桶位置，如 `CREATE TABLE`。或者，在除默认数据库之外的数据库内创建表。
+ 不支持在 AWS Glue 中重命名表。
+ 当您创建 Hive 表而不指定 `LOCATION` 时，表数据存储在通过 `hive.metastore.warehouse.dir` 属性指定的位置。默认情况下，这是 HDFS 中的一个位置。如果另一个集群需要访问该表，则它将失败，除非它有足够的权限访问创建该表的集群。此外，由于 HDFS 存储是暂时性的，因此如果集群终止，表数据将丢失，并且必须重新创建该表。我们建议您在使用 AWS Glue 创建 Hive 表时`LOCATION`在 Amazon S3 中指定。此外，也可以使用 `hive-site` 配置分类来为 `hive.metastore.warehouse.dir` 指定 Amazon S3 中的位置，它适用于所有 Hive 表。如果在 HDFS 位置创建了表，并且创建该表的集群仍在运行，则可以从 Glue 中将该表的位置更新为 Amazon S3 AWS 。有关更多信息，请参阅[《Glue *开发者指南》中的 “在 AWS Glue 控制台AWS 上*使用表格](https://docs.aws.amazon.com/glue/latest/dg/console-tables.html)”。
+ 不支持包含引号和撇号的分区值，例如 `PARTITION (owner="Doe's").`
+ emr-5.31.0 及更高版本支持[列统计数据](https://cwiki.apache.org/confluence/display/Hive/StatsDev#StatsDev-ColumnStatistics)。
+ 不支持使用 [Hive 授权](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Authorization)。作为替代方案，考虑使用[基于AWS Glue 资源的策略](https://docs.aws.amazon.com/glue/latest/dg/glue-resource-policies.html)。有关更多信息，请参阅[使用基于资源的策略获得 Amazon EMR 访问 Glue AWS 数据目录。](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-roles-glue.html)

使用 AWS Glue 数据目录作为带有 Spark 的 Apache Iceberg REST 目录时，请考虑以下几点：
+ 如果您将 Spark 会话目录与 Iceberg 结合使用（如[使用 Iceberg 和 Iceberg SparkCatalog 时的配置差异 SparkSessionCatalog](emr-iceberg-use-spark-cluster.md#emr-iceberg-spark-catalog)中所述），则除了将 AWS Glue Data Catalog 配置为 Apache Iceberg REST 目录之外，还必须将 AWS Glue Data Catalog 配置为 Apache Hive 元存储。
+  AWS Glue 数据目录 IRC 端点仅支持 Amazon Sigv4 身份验证方案。 OAuth 不支持。对于 OAuth 用户，请使用 IAM 身份中心配置访问权限。请参阅[将 Lake Formation 与 IAM Identity Center 连接](https://docs.aws.amazon.com/lake-formation/latest/dg/connect-lf-identity-center.html)。
+  AWS Glue Iceberg REST 目录并不支持开源中的所有操作。

# 在亚马逊 EMR 上使用 Spark 在 AWS Glue 数据目录中使用多目录层次结构
<a name="emr-multi-catalog"></a>

您可以注册您的 Amazon EMR 集群以访问 Gl AWS ue 数据目录，该目录使表格和其他目录资源可供各种使用者使用。 AWS Glue 数据目录支持多目录层次结构，可统一您在 Amazon S3 数据湖中的数据。它还提供了 Hive 元存储 API 和开源 Apache Iceberg REST API 来访问数据。这些功能适用于 Amazon EMR 和其他服务（例如 Amazon Athena 和 Amazon Redshift）。

## 目录资源如何组织
<a name="emr-lakehouse-org"></a>

当你在 AWS Glue 数据目录中创建资源时，你可以从任何支持 Apache Iceberg REST API 或 Hive 元数据仓的 SQL 引擎访问它们。 AWS Lake Formation 管理权限。

在 G AWS lue 数据目录中，数据按目录、数据库和表格的逻辑层次结构进行组织：
+ **目录**：保存数据存储中的对象（例如架构或表）的逻辑容器。
+ **用于存储 Redshift 托管存储 (RMS) 表的目录**：当您管理用于存储 RMS 表的目录时，可以使用 Iceberg 访问这些表。
+ **数据库**：在目录中组织数据对象（例如表和视图）。
+ **表和视图**：数据库中的数据对象，为抽象层提供可理解的架构。它们提供了一个用于访问底层数据的层，这些数据可以采用各种格式并且位于不同的位置。



## 配置用于 Amazon EMR 的数据目录
<a name="emr-lakehouse-configuration"></a>

首先，您需要将目录配置为支持 Amazon EMR 工具。 AWS Glue 数据目录提供 Hive 元存储兼容性，兼容 Iceberg REST。 APIs

**使用 Hive 元存储配置 Amazon EMR**

 有关如何设置的信息，请参阅 [AWS Glue 用户指南中的 Glue 数据目录对 Spark 作业的 AWS 支持](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-data-catalog-hive.html)。本主题介绍如何将 AWS Glue 数据目录配置为 Hive 元数据仓并使其可用作端点。此外，在使用 Glue 数据目录作为 Spark 的 A [pache Hive 元数据存储中，还有亚马逊 EMR 文档向您展示了如何将 G AWS lue 数据目录指定为](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-spark-glue.html) Spark 元数据库。 AWS 

## 访问 Glue 数据 AWS 目录中资源的权限
<a name="emr-lakehouse-using-irc-prereqs"></a>

本节介绍了使用 Amazon EMR 工具处理目录数据的 IAM 策略要求。向 AWS Glue Data Catalog 注册集群后，您需要以下权限才能发现随后创建的数据目录的创建和更改：
+ **胶水：GetCatalog**
+ **胶水：GetCatalogs**
+ **sts: AssumeRole**
+ **sts: TagSession**
+ **sts: SetContext**
+ **sts: SetSourceIdentity**

大多数情况下，分配权限时，我们建议创建一个 IAM 角色并为其分配权限。

此外，要查询目录数据，您必须使用 AWS Lake Formation设置数据目录的权限。有关在 AWS Lake Formation中设置数据目录权限的更多信息，请参阅[授予和撤销对 Data Catalog 资源的权限](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)。

在创建和配置集群并对目录对象设置权限后，您可以提交作业来查询和处理数据。

## 配置 Spark 以访问 AWS Glue 数据目录中的多目录层次结构
<a name="emr-lakehouse-using-spark-access"></a>

在 EMR 7.5 中，你可以将 Spark 配置为使用 AWS Glue 的多目录层次结构。多目录层次结构允许您执行以下操作：
+ 将现有 Amazon Redshift 数据仓库中的 Redshift 托管存储 (RMS) 数据（例如表、视图和物化视图）导入 Glue 数据目录。 AWS 您可以使用 EMR on EC2 和 EMR Serverless 查询这些对象。
+ 使用 ZeroeTL 创建 RMS 目录、Glue 数据目录并将数据存储在 RMS 中，并使用兼容 Iceberg 的查询引擎查询数据。 AWS 
+ 使用功能齐全的存储管理（包括压缩、快照和保留）在 AWS Glue 数据目录中创建托管 Iceberg 表。

### 初始化 Spark 会话时连接到多目录
<a name="emr-iceberg-initialize-spark-session-spark"></a>

以下示例演示了如何使用交互式 Spark shell、Spark submit 或 Amazon EMR Notebooks 来处理 Glue 的多目录层次结构。 AWS 

------
#### [ spark-shell ]

1. 使用 SSH 连接主节点。有关更多信息，请参阅《Amazon EMR 管理指南》**中的[使用 SSH 连接到主节点](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)。

1. 输入以下命令以启动 Spark shell。要使用 PySpark 外壳，请`spark-shell`替换为`pyspark`。

   ```
   spark-shell \
       --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
       --conf spark.sql.catalog.my_catalog.warehouse=s3://amzn-s3-demo-bucket/prefix/
       --conf spark.sql.catalog.my_catalog.type=glue \
       --conf spark.sql.catalog.my_catalog.glue.id=Glue RMS catalog ID \
       --conf spark.sql.defaultCatalog=my_catalog \
       --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
   ```

------
#### [ spark-submit ]

1. 使用 SSH 连接主节点。有关更多信息，请参阅《Amazon EMR 管理指南》**中的[使用 SSH 连接到主节点](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)。

1. 输入以下命令以为 Spark 启动 Spark 会话。

   ```
   spark-submit \
   --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
   --conf spark.sql.catalog.my_catalog.warehouse=s3://amzn-s3-demo-bucket1/prefix \
   --conf spark.sql.catalog.my_catalog.type=glue \
   --conf spark.sql.catalog.my_catalog.glue.id=Glue RMS catalog ID \
   --conf spark.sql.defaultCatalog=my_catalog \
   --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
   ```

------
#### [ EMR Studio notebooks ]

要使用 EMR Studio notebooks 初始化 Spark 会话，请使用 Amazon EMR notebook 中的 `%%configure` 魔法命令配置 Spark 会话，如以下示例所示。有关更多信息，请参阅 *Amazon EMR 管理指南*中的[使用 EMR Notebooks 魔法命令](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-studio-magics.html#emr-magics)。

```
%%configure -f{
"conf":{
    "spark.sql.catalog.my_catalog":"org.apache.iceberg.spark.SparkCatalog",
    "spark.sql.catalog.my_catalog.type":"glue",
    "spark.sql.catalog.my_catalog.glue.id":"Glue RMS catalog ID",
    "spark.sql.catalog.my_catalog.warehouse":"s3://amzn-s3-demo-bucket1/prefix/",
    "spark.sql.defaultCatalog", "my_catalog",
    "spark.sql.extensions":"org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions"
    }
}
```

------
#### [ CLI ]

要使用 CLI 初始化 Spark 会话，请运行下面的示例。有关使用 AWS CLI 和 Amazon EMR API 指定配置分类的更多信息，请参阅[配置](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps.html)应用程序。

```
[
  {
    "Classification": "spark-defaults",
    "Properties": {
      "spark.sql.catalog.my_catalog":"org.apache.iceberg.spark.SparkCatalog",
      "spark.sql.catalog.my_catalog.type":"glue",
      "spark.sql.catalog.my_catalog.glue.id":"Glue RMS catalog ID",
      "spark.sql.catalog.my_catalog.warehouse":"s3://amzn-s3-demo-bucket1/prefix/",
      "spark.sql.defaultCatalog", "my_catalog",
      "spark.sql.extensions":"org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions"
    }
  }
]
```

------

#### 使用 G AWS lue 数据目录初始化到 Redshift 托管存储的 Spark 会话
<a name="considerations-multi-catalog-glue-connect"></a>

以下示例命令使用 AWS Glue Data Catalog 初始化 Spark 会话。

```
spark-sql \
  --conf spark.sql.catalog.rms=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.rms.type=glue \
  --conf spark.sql.catalog.rms.glue.id=Glue RMS catalog ID \
  --conf spark.sql.defaultCatalog=rms
  --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
```

以下示例使用 Iceberg REST API 和带有 G AWS lue 数据目录的 Redshift 托管存储初始化 Spark 会话。

```
spark-sql \
  --conf spark.sql.catalog.rms=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.rms.type=rest \
  --conf spark.sql.catalog.rms.warehouse=glue RMS catalog ID \
  --conf spark.sql.catalog.rms.uri=Glue endpoint URI/iceberg \
  --conf spark.sql.catalog.rms.rest.sigv4-enabled=true \
  --conf spark.sql.catalog.rms.rest.signing-name=glue \
  --conf spark.sql.defaultCatalog=rms \
  --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
```

有关在 Spark Iceberg 中使用 AWS Glue 多目录层次结构的更多信息，请参阅将 Iceberg [集群与 Spark 配合使用](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-iceberg-use-spark-cluster.html)。

## 多目录配置的注意事项和限制
<a name="considerations-multi-catalog"></a>
+ 不支持将多目录层次结构与 Apache Hive 元存储结合使用。
+ 在使用 `SparkSessionCatalog` 时，将多目录层次结构与 Apache Hive 结合使用不支持回退到 Apache Hive 元存储。
+ 具有运行时角色的 EMR on EC2 集群不支持多目录层次结构。
+ 启用的 EC2 集群上的 EMR AWS Lake Formation 不支持多目录层次结构。

# 配置 Spark
<a name="emr-spark-configure"></a>

您可以使用配置分类配置 [Amazon EMR 上的 Spark](https://aws.amazon.com/elasticmapreduce/details/spark/)。有关使用配置分类的更多信息，请参阅 [配置应用程序](emr-configure-apps.md)。

Amazon EMR 上的 Spark 的配置分类包括如下：
+ **`spark`**：将 `maximizeResourceAllocation` 属性设置为 true 或 false。在设置为 true 时，Amazon EMR 将基于集群硬件配置自动配置 `spark-defaults` 属性。有关更多信息，请参阅 [使用 `maximizeResourceAllocation`](#emr-spark-maximizeresourceallocation)。
+ **`spark-defaults`**：在 `spark-defaults.conf` 文件中设置值。有关更多信息，请参阅 Spark 文档中的 [Spark 配置](https://spark.apache.org/docs/latest/configuration.html)。
+ **`spark-env`**：在 `spark-env.sh` 文件中设置值。有关更多信息，请参阅 Spark 文档中的[环境变量](https://spark.apache.org/docs/latest/configuration.html#environment-variables)。
+ **`spark-hive-site`**：在 `hive-site.xml` 中为 Spark 设置值。
+ **`spark-log4j`**：（Amazon EMR 版本 6.7.x 及更低版本）在 `log4j.properties` 文件中设置值。有关更多信息，请参阅 Github 上的 [log4j.properties.template](https://github.com/apache/spark/blob/branch-3.2/conf/log4j.properties.template) 文件。
+ **`spark-log4j2`**：（Amazon EMR 版本 6.8.0 及更高版本）在 `log4j2.properties` 文件中设置值。有关更多信息，请参阅 Github 上的 [log4j2.properties.template](https://github.com/apache/spark/blob/v3.3.0/conf/log4j2.properties.template) 文件。
+ **`spark-metrics`**：在 `metrics.properties` 文件中设置值。有关设置和更多信息，请参阅 Github 上的 [metrics.properties.template](https://github.com/apache/spark/blob/master/conf/metrics.properties.template) 文件和 Spark 文档中的[指标](https://spark.apache.org/docs/latest/monitoring.html#metrics)。

**注意**  
如果您要将 Spark 工作负载从另一个平台迁移到 Amazon EMR，我们建议您在添加自定义配置之前通过[Amazon EMR 设置的 Spark 默认值](#spark-defaults)检测工作负载。大多数客户都通过我们的默认设置见证了性能有所改善

**Topics**
+ [Amazon EMR 设置的 Spark 默认值](#spark-defaults)
+ [在 Amazon EMR 6.1.0 上配置 Spark 垃圾回收](#spark-gc-config)
+ [使用 `maximizeResourceAllocation`](#emr-spark-maximizeresourceallocation)
+ [配置节点停用行为](#spark-decommissioning)
+ [Spark ThriftServer 环境变量](#spark-thriftserver)
+ [更改 Spark 默认设置](#spark-change-defaults)
+ [从 Apache Log4j 1.x 迁移到 Log4j 2.x](#spark-migrate-logj42)

## Amazon EMR 设置的 Spark 默认值
<a name="spark-defaults"></a>

下表说明 Amazon EMR 如何在 `spark-defaults` 中设置影响应用程序的默认值。


**Amazon EMR 设置的 Spark 默认值**  

| 设置 | 说明 | 默认 值 | 
| --- | --- | --- | 
| spark.executor.memory | 每个执行程序进程要使用的内存量。例如：`1g`、`2g`。 |  此设置由集群中的核心实例和任务实例类型决定。  | 
| spark.executor.cores | 要对每个执行程序使用的内核的数量。 | 此设置由集群中的核心实例和任务实例类型决定。 | 
| spark.dynamicAllocation.enabled | 如果为 true，则使用动态资源分配，以基于工作负载增大和减小注册到应用程序的执行程序的数目。 |  `true`（使用 Amazon EMR 4.4.0 及更高版本）  Spark Shuffle Service 由 Amazon EMR 自动配置。   | 
| spark.sql.hive.advancedPartitionPredicatePushdown.enabled | 如果为 true，则启用高级分区谓词下推到 Hive 元数据仓。 | true | 
| spark.sql.hive.stringLikePartitionPredicatePushdown.enabled | 将 `startsWith`、`contains` 和 `endsWith` 筛选条件向下推送到 Hive 元数据仓中。  Glue 不支持 `startsWith`、`contains` 或 `endsWith` 谓词下推。如果您使用的是 Glue 元数据仓，并且由于这些函数的谓词向下推而遇到错误，请将此配置设置为 `false`。   | true | 

## 在 Amazon EMR 6.1.0 上配置 Spark 垃圾回收
<a name="spark-gc-config"></a>

使用 `spark.driver.extraJavaOptions` 和 `spark.executor.extraJavaOptions` 设置自定义垃圾回收配置会导致 Amazon EMR 6.1 中的驱动程序或执行程序启动失败，因为垃圾回收配置与 Amazon EMR 6.1.0 的配置存在冲突。对于 Amazon EMR 6.1.0，默认垃圾回收配置通过 `spark.driver.defaultJavaOptions` 和 `spark.executor.defaultJavaOptions` 设置。此配置仅适用于 Amazon EMR 6.1.0。与垃圾回收无关的 JVM 选项（例如用于配置日志记录（`-verbose:class`）的选项）仍然可以通过 `extraJavaOptions` 设置。有关更多信息，请参阅 [Spark 应用程序属性](https://spark.apache.org/docs/latest/configuration.html#application-properties)。

## 使用 `maximizeResourceAllocation`
<a name="emr-spark-maximizeresourceallocation"></a>

您可以使用 `spark` 配置分类将 `maximizeResourceAllocation` 设置为 `true`，以将执行程序配置为使用集群中的每个节点上尽可能多的资源。`maximizeResourceAllocation` 特定于 Amazon EMR。当您启用 `maximizeResourceAllocation`，Amazon EMR 会计算核心实例组中实例上的执行程序可用的最大计算和内存资源。然后，它将根据计算出的最大值设置相应的 `spark-defaults` 设置。

Amazon EMR 根据核心实例集中的实例类型计算执行程序可用的最大计算和内存资源。由于每个实例集可能具有不同的实例类型和大小，因此 Amazon EMR 使用的执行程序配置可能不适合您的集群，因此我们不建议在使用最大资源分配时使用默认设置。为您的实例集集群配置自定义设置。

**注意**  
您不应在带有其他分布式应用程序的集群上使用该`maximizeResourceAllocation`选项，例如 HBase。Amazon EMR 对分布式应用程序使用自定义 YARN 配置，这可能与 `maximizeResourceAllocation` 冲突并导致 Spark 应用程序失败。

以下是一个 `maximizeResourceAllocation` 设置为 `true` 的 Spark 分类配置。

```
[
  {
    "Classification": "spark",
    "Properties": {
      "maximizeResourceAllocation": "true"
    }
  }
]
```


**启用 `spark-defaults`时在 `maximizeResourceAllocation` 中配置的设置**  

| 设置 | 说明 | 值 | 
| --- | --- | --- | 
| spark.default.parallelism | 转换 RDDs 返回的默认分区数，例如join、 reduceByKey、parallelize（未由用户设置）。 |  对 YARN 容器可用的 CPU 内核数的 2 倍。  | 
| spark.driver.memory | 用于驱动程序进程的内存量， SparkContext 即初始化位置。 （例如，1g、2g）。 |  基于集群中的实例类型配置设置。但是，由于 Spark 驱动程序可在主实例或某个核心实例（例如，分别在 YARN 客户端和集群模式中）上运行，因此将根据这两个实例组中的实例类型的较小者进行设置。  | 
| spark.executor.memory | 每个执行者进程要使用的内存量。（例如，1g、2g） |  基于集群中的核心和任务实例类型配置设置。  | 
| spark.executor.cores | 要对每个执行程序使用的内核的数量。 | 基于集群中的核心和任务实例类型配置设置。 | 
| spark.executor.instances |  执行程序数。 |  基于集群中的核心和任务实例类型配置设置。除非同时将 `spark.dynamicAllocation.enabled` 显式设置为 true，否则将设置。  | 

## 配置节点停用行为
<a name="spark-decommissioning"></a>

使用 Amazon EMR 发行版 5.9.0 或更高版本时，Amazon EMR 上的 Spark 包含一组功能，有助于确保 Spark 正常处理因手动调整大小或自动扩展策略请求引起的节点终止。Amazon EMR 会在 Spark 中实施拒绝名单机制，该机制的基础是 YARN 停用机制。此机制有助于确保不会在即将停用的节点上计划新任务，同时允许正在运行的任务完成。此外，有些功能可以在节点终止导致随机数据块丢失时帮助更快地恢复 Spark 任务。可以更快触发并优化重新计算进程，从而加快重新计算和减少阶段重试，并防止因丢失随机数据块引发的提取失败所导致的任务失败。

**重要**  
Amazon EMR 发行版 5.11.0 中添加了 `spark.decommissioning.timeout.threshold` 设置，用于提升使用竞价型实例时的 Spark 恢复能力。在早期发行版中，当节点使用竞价型实例且该实例因出价而终止时，Spark 可能无法正常地处理终止。任务可能失败，而且随机重新计算可能花费大量时间。为此，如果您使用竞价型实例，建议使用发行版 5.11.0 或更高版本。


**Spark 节点停用设置**  

| 设置 | 说明 | 默认 值 | 
| --- | --- | --- | 
|  `spark.blacklist.decommissioning.enabled`  |  当设置为 `true`，YARN 中的 Spark 拒绝名单节点处于 `decommissioning` 状态。Spark 不在于该节点上运行的执行程序上安排新任务。允许已经在运行的任务完成。  |  `true`  | 
|  `spark.blacklist.decommissioning.timeout`  |  处于 `decommissioning` 状态的节点被加入拒绝名单的时间量。默认情况下，此值设置成一小时，这也是 `yarn.resourcemanager.decommissioning.timeout` 的默认值。要确保节点在其整个退役周期内都处于拒绝名单中，请将此值设置为等于或大于 `yarn.resourcemanager.decommissioning.timeout`。在停用超时过期后，节点转为 `decommissioned` 状态，并且 Amazon EMR 可能终止节点的 EC2 实例。如果超时过期后有任何任务仍在运行，这些任务会丢失或被终止并在于其他节点上运行的其他执行程序上重新安排。  |  `1h`  | 
|  `spark.decommissioning.timeout.threshold`  |  在 Amazon EMR 发行版 5.11.0 或更高版本中可用。以秒为单位指定。当某个节点转为停用状态时，如果主机将在等于或小于此值的时段后停用，Amazon EMR 不仅会将此节点加入拒绝名单，还会清除主机状态（通过 `spark.resourceManager.cleanupExpiredHost` 指定），而不会等待此节点转换为停用状态。这使 Spark 能够更好地处理竞价型实例终止，因为无论 `yarn.resourcemager.decommissioning.timeout` 的值如何，Spot 实例都会在 20 秒的超时时间后停用，因此可能没有足够的时间提供其他节点来随机读取文件。  |  `20s`  | 
|  `spark.resourceManager.cleanupExpiredHost`  |  当设置为 `true` 时，Spark 会注销处于 `decommissioned` 状态的节点上的执行程序存储的所有已缓存数据和随机数据块。这会加速恢复过程。  |  `true`  | 
|  `spark.stage.attempt.ignoreOnDecommissionFetchFailure`  |  当设置为 `true` 时，有助于防止 Spark 进入失败阶段并因为从退役节点获取失败次数过多而导致任务失败。从处于 `decommissioned` 状态的节点获取随机数据块失败的次数不会计入连续获取失败的最大数量。  | true | 

## Spark ThriftServer 环境变量
<a name="spark-thriftserver"></a>

Spark 将 Hive Thrift 服务器端口环境变量 `HIVE_SERVER2_THRIFT_PORT` 设置为 10001。

## 更改 Spark 默认设置
<a name="spark-change-defaults"></a>

您可以使用 `spark-defaults` 配置分类或 `spark` 配置分类中的 `maximizeResourceAllocation` 设置更改 `spark-defaults.conf` 中的默认值。

以下过程说明如何使用 CLI 或控制台修改设置。

**使用 CLI 创建一个 spark.executor.memory 设为 2g 的集群**
+ 使用以下命令创建一个安装了 Spark 且 `spark.executor.memory` 设为 2g 的集群，该集群引用存储在 Amazon S3 中的 `myConfig.json` 文件。

  ```
  aws emr create-cluster --release-label emr-7.12.0 --applications Name=Spark \
  --instance-type m5.xlarge --instance-count 2 --service-role EMR_DefaultRole_V2 --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole --configurations https://s3.amazonaws.com/amzn-s3-demo-bucket/myfolder/myConfig.json
  ```
**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

  `myConfig.json`:

  ```
  [
      {
        "Classification": "spark-defaults",
        "Properties": {
          "spark.executor.memory": "2G"
        }
      }
    ]
  ```

**使用控制台创建一个 spark.executor.memory 设为 2g 的集群**

1. 导航到 Amazon EMR 新控制台，然后从侧面导航栏中选择**切换到旧控制台**。有关切换到旧控制台后预期情况的更多信息，请参阅 [Using the old console](https://docs.aws.amazon.com/emr/latest/ManagementGuide/whats-new-in-console.html#console-opt-in)。

1. 依次选择 **Create cluster (创建集群)**、**Go to advanced options (转到高级选项)**。

1. 选择 **Spark**。

1. 在 **Edit software settings (编辑软件设置)** 下，将 **Enter configuration (输入配置)** 保留选中状态并输入以下配置：

   ```
   classification=spark-defaults,properties=[spark.executor.memory=2G]
   ```

1. 选择其他选项，选择 ****，然后选择** Create cluster (创建集群)**。

**要设置 maximizeResourceAllocation**
+ 使用存储在 Amazon S3 中的文件 AWS CLI，创建安装了 Spark 并将其`maximizeResourceAllocation`设置为 true 的集群。`myConfig.json`

  ```
  aws emr create-cluster --release-label emr-7.12.0 --applications Name=Spark \
  --instance-type m5.xlarge --instance-count 2 --service-role EMR_DefaultRole_V2 --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole --configurations https://s3.amazonaws.com/amzn-s3-demo-bucket/myfolder/myConfig.json
  ```
**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

  `myConfig.json`:

  ```
  [
    {
      "Classification": "spark",
      "Properties": {
        "maximizeResourceAllocation": "true"
      }
    }
  ]
  ```

**注意**  
对于 Amazon EMR 5.21.0 及更高版本，您可以覆盖集群配置，并为运行的集群中的每个实例组指定额外的配置分类。您可以使用 Amazon EMR 控制台、 AWS Command Line Interface (AWS CLI) 或软件开发工具包来执行此操作。 AWS 有关更多信息，请参阅[为运行的集群中的实例组提供配置](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps-running-cluster.html)。

## 从 Apache Log4j 1.x 迁移到 Log4j 2.x
<a name="spark-migrate-logj42"></a>

[Apache Spark](https://aws.amazon.com/emr/features/spark/) 版本 3.2.x 及更早版本使用旧版 Apache Log4j 1.x 和 `log4j.properties` 文件在 Spark 进程中配置 Log4j。Apache Spark 版本 3.3.0 及更高版本使用 Apache Log4j 2.x 和 `log4j2.properties` 文件在 Spark 进程中配置 Log4j。

如果您使用低于 6.8.0 的 Amazon EMR 版本配置了 Apache Spark Log4j，则必须删除旧版 `spark-log4j` 配置分类并迁移到 `spark-log4j2` 配置分类和密钥格式，然后才能升级到 Amazon EMR 6.8.0 或更高版本。在 Amazon EMR 版本 6.8.0 及更高版本中，旧版 `spark-log4j` 分类会导致集群创建失败并出现 `ValidationException` 错误。不会因为与 Log4j 不兼容相关的故障而向您收费，但您必须删除已失效的 `spark-log4j` 配置分类才能继续。

有关从 Apache Log4j 1.x 迁移到 Log4j 2.x 的更多信息，请参阅 Github 上的《[Apache Log4j 迁移指南](https://logging.apache.org/log4j/2.x/manual/migration.html)》和 [Spark Log4j 2 模板](https://github.com/apache/spark/blob/master/conf/log4j2.properties.template)。

**注意**  
对于 Amazon EMR，Apache Spark 使用 `log4j2.properties` 文件，而不是《Apache Log4j 迁移指南》[https://logging.apache.org/log4j/2.x/manual/migration.html](https://logging.apache.org/log4j/2.x/manual/migration.html)中所述的 .xml 文件。此外，我们不建议使用 Log4j 1.x 桥接方法转换为 Log4j 2.x。

# 什么是 Amazon EMR 的 Apache Spark 故障排除代理
<a name="spark-troubleshoot"></a>

## 简介
<a name="spark-troubleshooting-agent-intro"></a>

适用于亚马逊 EMR 的 Apache Spark 故障排除代理是一项对话式 AI 功能，可简化亚马逊 EMR、 AWS Glue 和亚马逊笔记本上 Apache Spark 应用程序的故障排除。 SageMaker 传统的 Spark 故障排除需要对日志、性能指标和错误模式进行大量手动分析，以确定根本原因和代码修复。代理通过自然语言提示、自动工作负载分析和智能代码建议来简化此过程。

您可以使用代理来排除故障 PySpark 和 Scala 应用程序故障。代理会分析您失败的作业，识别性能瓶颈，并提供可行的建议和代码修复，同时让您完全控制实施决策。

**注意**  
作为 Amazon EMR 的一部分，Apache Spark 故障排除代理无需支付额外费用。代理仅提供分析和建议。您只需为运行应用程序以验证任何建议的修复程序时使用的 Amazon EMR 资源付费。

## 架构概述
<a name="spark-troubleshooting-agent-architecture"></a>

故障排除代理有三个主要组件：开发环境中用于交互的兼容 MCP 的人工智能助手、用于处理客户端与 AWS 服务之间安全通信和身份验证的 [MCP 代理，以及为 AWS](https://github.com/aws/mcp-proxy-for-aws)亚马逊 EMR、Glue 和亚马逊笔记本电脑提供专门的 Spark 故障排除工具的 Amazon SageMaker Unified Studio 远程 MCP 服务器`(preview)`。 AWS SageMaker 下图说明了你如何通过 AI Assistant 与 Amazon SageMaker Unified Studio 远程 MCP 服务器进行交互。

![\[Spark 故障排除代理架构。\]](http://docs.aws.amazon.com/zh_cn/emr/latest/ReleaseGuide/images/spark-troubleshooting-agent-architecture.png)


AI 助手将按照以下步骤使用 MCP 服务器提供的专用工具来协调故障排除：
+ **功能提取和上下文构建：**代理自动收集和分析来自 Spark 应用程序的遥测数据，包括 Spark History Server 日志、配置设置和错误跟踪。它提取关键性能指标、资源利用率模式和故障签名，为智能故障排除构建全面的上下文配置文件。
+ **GenAI 根本原因分析器和推荐引擎：**该代理利用 AI 模型和 Spark 知识库来关联提取的特征并确定性能问题或故障的根本原因。它提供诊断见解和分析 Spark 应用程序执行中出了什么问题。
+ **GenAI Spark 代码建议：**根据上一步中的根本原因分析，代理会分析您现有的代码模式，并确定需要修复应用程序故障代码的低效操作。它提供了切实可行的建议，包括具体的代码修改、配置调整和架构改进，并附有具体的示例。

**Topics**
+ [简介](#spark-troubleshooting-agent-intro)
+ [架构概述](#spark-troubleshooting-agent-architecture)
+ [故障排除代理的设置](spark-troubleshooting-agent-setup.md)
+ [使用故障排除代理](spark-troubleshooting-using-troubleshooting-agent.md)
+ [特性和功能](spark-troubleshooting-features.md)
+ [故障排除和问答](spark-troubleshooting-agent-troubleshooting.md)
+ [Spark 故障排除代理工作流程详情](spark-troubleshooting-agent-workflow.md)
+ [提示示例](spark-troubleshooting-agent-prompt-examples.md)
+ [IAM 角色设置](spark-troubleshooting-agent-iam-setup.md)
+ [使用 Spark 故障排除工具](spark-troubleshooting-agent-using-tools.md)
+ [为亚马逊 SageMaker 统一工作室 MCP 配置接口 VPC 终端节点](spark-troubleshooting-agent-vpc-endpoints.md)
+ [Apache Spark 故障排除代理的跨区域处理](spark-troubleshooting-cross-region-processing.md)
+ [使用记录亚马逊 SageMaker 统一工作室 MCP 通话 AWS CloudTrail](spark-troubleshooting-cloudtrail-integration.md)
+ [Apache Spark 代理的服务改进](spark-agents-service-improvements.md)

# 故障排除代理的设置
<a name="spark-troubleshooting-agent-setup"></a>

**注意**  
Apache Spark 故障排除代理使用跨区域推理来处理自然语言请求并生成响应。欲了解更多详情，请参阅[Apache Spark 故障排除代理的跨区域处理](spark-troubleshooting-cross-region-processing.md)。Amazon SageMaker Unified Studio MCP 服务器处于预览状态，可能会发生变化。

## 先决条件
<a name="spark-troubleshooting-agent-prerequisites"></a>

在我们开始与 Kiro CLI 集成的设置过程之前，请确保在您的工作站上安装了以下内容：
+  [安装 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 
+  [安装 Python 3.10\$1](https://www.python.org/downloads/release/python-3100/) 
+  [安装适用于 [MCP 代理](https://github.com/aws/mcp-proxy-for-aws?tab=readme-ov-file)的`uv`软件包管理器](https://docs.astral.sh/uv/getting-started/installation/) AWS
+  [安装 Kiro CLI](https://kiro.dev/docs/cli/) 
+ AWS 配置的本地证书（通过 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)、环境变量或 IAM 角色）-用于本地操作，例如上传升级后的作业工件以执行 EMR 验证任务。

## 安装资源
<a name="spark-troubleshooting-agent-setup-resources"></a>

您可以使用 AWS CloudFormation 模板为 MCP 服务器设置资源。这些模板是您应修改以满足要求的示例。该模板为故障排除过程创建了以下资源：

1. IAM 角色，该角色具有调用 MCP 服务器的权限以及所选平台的故障排除过程所需的权限。

选择下表中的 **Launch Stack (启动堆栈)** 按钮之一。这将在相应区域的主 AWS CloudFormation 机上启动堆栈。


| Region | 启动 | 
| --- | --- | 
| 美国东部（俄亥俄州） |  [https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-us-east-2.s3.us-east-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-us-east-2.s3.us-east-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 美国东部（弗吉尼亚州北部） |  [https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-us-east-1.s3.us-east-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-us-east-1.s3.us-east-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 美国西部（俄勒冈） |  [https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-us-west-2.s3.us-west-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-us-west-2.s3.us-west-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 亚太地区（东京） |  [https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-northeast-1.s3.ap-northeast-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-northeast-1.s3.ap-northeast-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 欧洲地区（爱尔兰） |  [https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-west-1.s3.eu-west-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-west-1.s3.eu-west-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 亚太地区（新加坡） |  [https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-southeast-1.s3.ap-southeast-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-southeast-1.s3.ap-southeast-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 亚太地区（悉尼） |  [https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-southeast-2.s3.ap-southeast-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-southeast-2.s3.ap-southeast-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 加拿大（中部） |  [https://console.aws.amazon.com/cloudformation/home?region=ca-central-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ca-central-1.s3.ca-central-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=ca-central-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ca-central-1.s3.ca-central-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 南美洲（圣保罗） |  [https://console.aws.amazon.com/cloudformation/home?region=sa-east-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-sa-east-1.s3.sa-east-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=sa-east-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-sa-east-1.s3.sa-east-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 欧洲地区（法兰克福） |  [https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-central-1.s3.eu-central-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-central-1.s3.eu-central-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 欧洲地区（斯德哥尔摩） |  [https://console.aws.amazon.com/cloudformation/home?region=eu-north-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-north-1.s3.eu-north-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=eu-north-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-north-1.s3.eu-north-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 欧洲地区（伦敦） |  [https://console.aws.amazon.com/cloudformation/home?region=eu-west-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-west-2.s3.eu-west-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=eu-west-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-west-2.s3.eu-west-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| Europe (Paris) |  [https://console.aws.amazon.com/cloudformation/home?region=eu-west-3#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-west-3.s3.eu-west-3.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=eu-west-3#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-eu-west-3.s3.eu-west-3.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 亚太地区（首尔） |  [https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-northeast-2.s3.ap-northeast-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-2#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-northeast-2.s3.ap-northeast-2.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 
| 亚太地区（孟买） |  [https://console.aws.amazon.com/cloudformation/home?region=ap-south-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-south-1.s3.ap-south-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup](https://console.aws.amazon.com/cloudformation/home?region=ap-south-1#/stacks/new?templateURL=https%3A%2F%2Fsmus-mcp-cfn-template-prod-ap-south-1.s3.ap-south-1.amazonaws.com%2Fcloudformation%2Fspark-troubleshooting-mcp-setup.yaml&stackName=spark-troubleshooting-mcp-setup)  | 

进入**指定堆栈详细信息**页面，输入**堆栈名称**。在 **Parameters**（参数）下输入其他信息。提供以下信息，然后继续创建堆栈。
+ **TroubleshootingRoleName**-要为故障排除操作创建的 IAM 角色的名称
+ **启用 EMREC2**-启用 EMR-EC2 故障排除权限（默认值：true）
+ **启用 EMRServerless**-启用 EMR 无服务器故障排除权限（默认值：true）
+ **EnableGlue**-启用 Glue 疑难解答权限（默认值：true）
+ **CloudWatchKmsKeyArn**-（可选）用于 CloudWatch 日志加密的现有 KMS 密钥的 ARN（仅限 EMR Serverless，默认加密时留空）

您也可以下载并查看[ CloudFormation 模板](https://github.com/aws-samples/aws-emr-utilities/blob/03c20fece616de23ec0ea5389f0113a5bc65fc3a/utilities/apache-spark-agents/spark-troubleshooting-agent-cloudformation/spark-troubleshooting-mcp-setup.yaml)，指定上述选项，然后 CloudFormation 使用 CLI 命令自行启动模板，示例见下文：

```
# deploy the stack with CloudFormation CLI commands
aws cloudformation deploy \
  --template-file spark-troubleshooting-mcp-setup.yaml \
  --stack-name spark-troubleshooting-mcp-setup \
  --region <your Spark MCP server launch region> \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides \
    TroubleshootingRoleName=spark-troubleshooting-role


# retrieve the 1-line instruction to set the local environment variables, which will be used for the following MCP server configuration
aws cloudformation describe-stacks \
  --stack-name spark-troubleshooting-mcp-setup \
  --region <your Spark MCP server launch region> \
  --query "Stacks[0].Outputs[?OutputKey=='ExportCommand'].OutputValue" \
  --output text
```

打开 “输出” 选项卡（或从上面的 desc CloudFormation ribe-stacks CLI 命令中检索），从输出中复制单行指令以设置环境变量，然后 CloudFormation 在本地环境中执行该指令。单行指令示例：

```
export SMUS_MCP_REGION=<your mcp server launch region> && export IAM_ROLE=arn:aws:iam::111122223333:role/spark-troubleshooting-role-xxxxxx
```

然后在本地运行以下命令来设置 IAM 配置文件和 MCP 服务器配置：

```
# Step 1: Configure AWS CLI Profile
aws configure set profile.smus-mcp-profile.role_arn ${IAM_ROLE}
aws configure set profile.smus-mcp-profile.source_profile <AWS CLI Profile to assume the IAM role - ex: default>
aws configure set profile.smus-mcp-profile.region ${SMUS_MCP_REGION}

# Step 2: if you are using kiro CLI, use the following command to add the MCP configuration
# Add Spark Troubleshooting MCP Server
kiro-cli-chat mcp add \
    --name "sagemaker-unified-studio-mcp-troubleshooting" \
    --command "uvx" \
    --args "[\"mcp-proxy-for-aws@latest\",\"https://sagemaker-unified-studio-mcp.${SMUS_MCP_REGION}.api.aws/spark-troubleshooting/mcp\", \"--service\", \"sagemaker-unified-studio-mcp\", \"--profile\", \"smus-mcp-profile\", \"--region\", \"${SMUS_MCP_REGION}\", \"--read-timeout\", \"180\"]" \
    --timeout 180000 \
    --scope global
    
# Add Spark Code Recommendation MCP Server
kiro-cli-chat mcp add \
    --name "sagemaker-unified-studio-mcp-code-rec" \
    --command "uvx" \
    --args "[\"mcp-proxy-for-aws@latest\",\"https://sagemaker-unified-studio-mcp.${SMUS_MCP_REGION}.api.aws/spark-code-recommendation/mcp\", \"--service\", \"sagemaker-unified-studio-mcp\", \"--profile\", \"smus-mcp-profile\", \"--region\", \"${SMUS_MCP_REGION}\", \"--read-timeout\", \"180\"]" \
    --timeout 180000 \
    --scope global
```

这应该`~/.kiro/settings/mcp.json`会更新以包括下面的 MCP 服务器配置。

```
{
  "mcpServers": {
    "sagemaker-unified-studio-mcp-troubleshooting": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws@latest",
        "https://sagemaker-unified-studio-mcp.us-east-1.api.aws/spark-troubleshooting/mcp",
        "--service",
        "sagemaker-unified-studio-mcp",
        "--profile",
        "smus-mcp-profile",
        "--region",
        "us-east-1",
        "--read-timeout",
        "180"
      ],
      "timeout": 180000,
      "disabled": false
    },
    "sagemaker-unified-studio-mcp-code-rec": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws@latest",
        "https://sagemaker-unified-studio-mcp.us-east-1.api.aws/spark-code-recommendation/mcp",
        "--service",
        "sagemaker-unified-studio-mcp",
        "--profile",
        "smus-mcp-profile",
        "--region",
        "us-east-1",
        "--read-timeout",
        "180"
      ],
      "timeout": 180000,
      "disabled": false
    }
  }
}
```

有关不同 MCP 客户端（例如 Kiro、Cline 和）的配置指南，请参阅[支持的接口](spark-troubleshooting-using-troubleshooting-agent.md#supported-interfaces)。 GitHub CoPilot

# 使用故障排除代理
<a name="spark-troubleshooting-using-troubleshooting-agent"></a>

## 支持的部署模式
<a name="supported-deployment-modes"></a>

适用于 Amazon EMR 的 Apache Spark 故障排除代理支持针对失败的 Spark 工作负载的全面分析功能，包括自动错误诊断、性能瓶颈识别、代码建议和可行的建议，以提高以下 Spark 部署模式下的应用程序性能：
+ EC2 上的 EMR
+ EMR Serverless
+ AWS Glue

请参阅[特性和功能](spark-troubleshooting-features.md)以了解详细的功能、容量和限制。

## 支持的接口
<a name="supported-interfaces"></a>

### 对 Amazon SageMaker 笔记本中的单元进行故障排除
<a name="troubleshooting-sagemaker-notebooks"></a>

演示使用 Amazon SageMaker 笔记本电脑的故障排除经验。对于任何笔记本手机故障，您可以通过单击`Fix with AI`按钮让 Amazon SageMaker Notebook Agent 对故障进行故障排除，请求进行分析，然后进行可能的代码修复（如果错误是由代码引起的）。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/btW8hwio0tE/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/btW8hwio0tE)


### 使用 Kiro CLI 对 Glue 和 EMR Spark 应用程序进行故障排除
<a name="troubleshooting-glue-emr-applications"></a>

启动 Kiro CLI 或你的 AI Assistant，然后验证已加载的工具以进行故障排除。

```
...
 sagemaker-unified-studio-mcp-code-rec (MCP)
 - spark_code_recommendation    not trusted
 
 sagemaker-unified-studio-mcp-troubleshooting (MCP)
 - analyze_spark_workload       not trusted
...
```

现在，您可以启动 Spark 故障排除代理工作流程了。

演示 Kiro CLI 的故障排除体验。您只需按以下提示即可开始故障排除过程：

```
Analyze my Glue job. The job name is "xxx" and the job run id is "xxx"
```

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/YLwV_EenJXY/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/YLwV_EenJXY)


### 与其他 MCP 客户端集成
<a name="integration-other-mcp-clients"></a>

中所述的配置也[故障排除代理的设置](spark-troubleshooting-agent-setup.md)可以在其他 MCP 客户端中使用，也可以用于 IDEs 连接到托管 MCP 服务器：
+ **与 Cline 集成**-要将 MCP 服务器与 Cline 配合使用，请修改`cline_mcp_settings.json`并添加上面的配置。有关如何管理 M [CP 配置的更多信息，请参阅 Cline 的文档](https://docs.cline.bot/mcp/configuring-mcp-servers)。
+ **与 Claude Code 集成**要将 MCP 服务器与 Claude Code 一起使用，请修改配置文件以包含 MCP 配置。文件路径因操作系统而异。有关详细设置，请参阅 [ https://code.claude.com/docs/en/mcp](https://code.claude.com/docs/en/mcp)。
+ **与 C GitHub opilot 集成**-要将 MCP 服务器与 C GitHub opilot 一起使用，请按照 [ https://docs.github.com/en/copilot/how-tos/provide-context/use-mcp/extend-copilot-chat-with-mcp](https://docs.github.com/en/copilot/how-tos/provide-context/use-mcp/extend-copilot-chat-with-mcp) 中的说明修改相应的配置文件，然后按照每个 IDE 的说明激活安装程序。

# 特性和功能
<a name="spark-troubleshooting-features"></a>

## 支持的平台
<a name="supported-platforms"></a>
+ **语言**：Python 和 Scala Spark 应用程序
+ **目标平台**：亚马逊 EMR、EMR Serverless 和 Glue AWS 

## 工作方式
<a name="how-it-works"></a>

当你的 Spark 应用程序失败时，你可以使用故障排除代理自动调查出了什么问题。它会分析您的 Spark 事件日志、错误消息和资源使用情况，以查明确切的问题——无论是 Spark 执行器内存不足、配置错误还是代码错误。

当你要求自然语言提示分析你的 Spark 工作负载时，代理会连接到你平台的资源并提取功能（包括 Spark 事件日志、查询计划、执行者时间表、日志跟踪、配置和指标）：
+ 在 EMR-EC2 上：它连接到集群的 [EMR 持久用户界面](https://docs.aws.amazon.com/emr/latest/ManagementGuide/app-history-spark-UI.html)
+ On Glue：它从 Glue Studio 的 [Spark 用户界面](https://docs.aws.amazon.com/glue/latest/dg/monitor-spark-ui-jobs.html)中为这项工作构建上下文
+ [在 EMR-Serverless 上：它连接到 EMR-Serverless Spark 历史服务器来完成任务](https://docs.aws.amazon.com/emr-serverless/latest/APIReference/API_GetDashboardForJobRun.html)
+ 代理还会分析您的错误堆栈跟踪和配置详细信息，为您提供切实可行的见解。

对于失败的工作负载，您将获得明确的根本原因说明和修复它的具体步骤。如果代理检测到与代码相关的问题，它会自动提供代码建议，以显示要在代码中更改的确切内容。您也可以随时直接请求代码级建议，无需进行全面分析。

## 可用区
<a name="available-regions"></a>

Spark 故障排除代理可在以下区域使用：
+ **亚太地区**：东京（ap-northeast-1）、首尔（ap-northeast-2）、新加坡（ap-southeast-1）、悉尼（ap-southeast-2）和孟买（ap-southeast-1）和孟买（ap-southeast-1）
+ **北美洲**：加拿大（ca-central-1）
+ **欧洲**：斯德哥尔摩（eu-north-1）、爱尔兰（eu-west-1）、伦敦（eu-west-2）、巴黎（eu-west-3）和法兰克福（eu-central-1）
+ **南美洲**：圣保罗（sa-east-1）
+ **美国**：弗吉尼亚州北部（us-east-1）、俄亥俄州（us-east-2）和俄勒冈州（us-west-2）

## Spark 故障排除范围和用户要求
<a name="scope-requirements"></a>
+ **支持的 Spark 工作负载状态**：这些工具将仅支持对失败的 Spark 工作负载的响应。
+ **EMR 持久用户界面：**在分析 Amazon EMR-EC2 工作负载时，分析工具将尝试连接到 EMR 持久用户界面以检索关键 Spark 信息。[此处记录了 EMR 持久用户界面的注意事项。](https://docs.aws.amazon.com/emr/latest/ManagementGuide/app-history-spark-UI.html#app-history-spark-UI-limitations)
+ **Glue Studio Spark 用户界面**：在分析 AWS Glue 工作负载时，分析工具将尝试通过解析亚马逊 S3 中用户的 Spark 事件日志来检索 Spark 的关键信息。[此处](https://docs.aws.amazon.com/glue/latest/dg/monitor-spark-ui-jobs.html)记录了允许的最大 Spark 事件日志大小：512 MB，滚动日志为 2 GB。
+ **代码建议：**仅支持 Amazon EMR-EC2 和 AWS Glue 工作负载的工作负 PySpark 载
+ **区域资源：**Spark 故障排除代理是区域性的，使用该区域的底层 EMR 资源进行故障排除。不支持跨区域故障排除。

# 故障排除和问答
<a name="spark-troubleshooting-agent-troubleshooting"></a>

## 问题排查
<a name="spark-troubleshooting-common-issues"></a>

对于不同的 MCP 客户端，来自 Spark 故障排除代理的错误消息有不同的可用方式。在本页中，我们列出了一些使用适用于 Amazon EMR 的 Apache Spark 疑难解答代理时可能遇到的常见问题的一般指南。

主题
+ [错误：MCP 服务器加载失败](#mcp-server-failed-to-load)
+ [观察：工具加载缓慢](#slow-tool-loading)
+ [错误：工具调用失败，出现限制错误](#throttling-error)
+ [错误：工具响应用户错误](#user-error)
+ [错误：工具响应内部错误](#internal-error)

### 错误：MCP 服务器加载失败
<a name="mcp-server-failed-to-load"></a>
+ 验证您的 MCP 配置是否正确配置。
+ **验证 JSON 语法**：
  + 确保你的 JSON 有效且没有语法错误
  + 检查是否缺少逗号、引号或方括号
+ 验证您的本地 AWS 证书并验证 MCP IAM 角色的策略配置是否正确。
+ 运行 /mcp 以验证 MCP 服务器的可用性 `Kiro-CLI`

### 观察：工具加载缓慢
<a name="slow-tool-loading"></a>
+ 首次尝试启动服务器时，可能需要几秒钟才能加载工具。
+ 如果工具未出现，请尝试重新开始聊天。
+ 运行`/tools`命令以验证工具可用性。
+ `/mcp`如果服务器启动时没有出错，则运行。

### 错误：工具调用失败，出现限制错误
<a name="throttling-error"></a>
+ 如果您达到服务限制，请等待几秒钟以发出工具调用（如果您看到限制异常）。

### 错误：工具响应用户错误
<a name="user-error"></a>
+ AccessDeniedException -检查错误消息并修复权限问题。
+ InvalidInputException -检查错误消息并更正刀具输入参数。
+ ResourceNotFoundException -检查错误消息并修复资源引用的输入参数。

### 错误：工具响应内部错误
<a name="internal-error"></a>
+ 如果您看到，`The service is handling high-volume requests`请在几秒钟后重试工具调用。
+ 如果您看到，`INTERNAL SERVICE EXCEPTION`请记录分析 ID、工具名称、mcp 日志或工具响应中提供的任何错误消息以及可选的经过清理的对话历史记录，然后联系支持人员。 AWS 

## 问答
<a name="spark-troubleshooting-qa"></a>

### 1. 我是否应该默认为工具启用 “信任” 设置？
<a name="qa-trust-setting"></a>

接受代码建议时，请勿在默认情况下为所有工具调用打开 “信任” 设置，也不要在 git 版本化的构建环境中进行操作。查看每个工具的执行情况，以了解正在进行哪些更改。

### 2. 使用故障排除工具的常见示例提示有哪些？
<a name="qa-example-prompts"></a>

有关利用故障排除工具的提示示例，请参阅。[提示示例](spark-troubleshooting-agent-prompt-examples.md)

### 3. 哪些数据会传输到法学硕士学位以及如何处理这些数据？
<a name="qa-data-transmitted-to-llm"></a>

客户数据和文件保留在您选择的 AWS 区域内，不会跨区域传输。当代理在使用来自 Amazon Bedrock 的全球跨区域推理的区域运营时，该服务可能会根据需求将请求路由到最近的具有可用容量的区域。在这种情况下，仅传输从客户日志中提取的元数据和经过处理的推理结果，而不传输底层客户数据或文件。无论推理发生在同一区域内还是路由到另一个区域，所有数据在发送到 LLM 进行处理之前都经过了 PII 屏蔽。有关跨区域推理的工作原理以及哪些区域受到影响的更多详细信息，请参阅。[Apache Spark 故障排除代理的跨区域处理](spark-troubleshooting-cross-region-processing.md)

# Spark 故障排除代理工作流程详情
<a name="spark-troubleshooting-agent-workflow"></a>

要启动故障排除流程，您需要访问在支持的平台（EMR-EC2、EMR Serverless、G AWS lue 或 Amazon D SageMaker ata Notebook）上运行的失败的 Spark 应用程序标识符。应用程序应具有可访问的日志、Spark 历史服务器和配置详细信息。确保您拥有访问平台资源和应用程序元数据的必要权限。确定这些要求后，您可以提交如下提示以启动故障排除工作流程：

```
Analyze my EMR step execution failure, EMR id <step-id> with cluster id <cluster-id>
```

此时，代理将使用专门的工具协调故障排除。工作流程遵循以下步骤：

1. **功能提取和上下文构建**：代理自动收集和分析来自 Spark 应用程序的遥测数据，包括历史服务器日志、配置设置和错误跟踪。您将看到该工具收集有关性能指标、资源利用模式和故障签名的信息。

1. **分析和根本原因识别**：代理利用 AI 模型和 Spark 知识库来关联提取的特征并确定性能问题或故障的根本原因。你会收到：
   + **分析见解**：有关代理发现和分析内容的技术细节。
   + **根本原因**：清楚地解释出了什么问题和原因。
   + **初步评估**：无论问题与代码相关、配置相关还是资源相关，都将提供一些一般指导和分析以缓解措施。

1. **代码建议**（如果适用）：如果分析根据错误分类发现了与代码相关的问题，则工程师可以建议利用代码推荐工具提供具体建议，以使用精确的代码和建议的替换来实施建议的 before/after 代码修复。

故障排除过程是迭代的，您可以继续对话以更深入地研究具体问题；您还可以在我们的本地 Spark 代码开发中以交互方式使用这些工具来解决代码错误或持续改进代码。

# 提示示例
<a name="spark-troubleshooting-agent-prompt-examples"></a>

以下是可在故障排除体验中使用的提示示例列表。

## 1. 解决 Spark 作业执行失败问题
<a name="troubleshoot-job-failure"></a>

EC2 上的 EMR 疑难解答：

```
Troubleshoot my EMR-EC2 step with id s-xxxxxxxxxxxx on cluster j-xxxxxxxxxxxxx
```

Glue Job 疑难解答：

```
Troubleshoot my Glue job with job run id jr_xxxxxxxxxxxxxxxxxxxxxxxxxxxx and job name test_job
```

EMR 无服务器故障排除：

```
Troubleshoot my EMR-Serverless job run with application id 00xxxxxxxx and job run id 00xxxxxxxx
```

## 2. 请求代码修复建议
<a name="request-code-fix"></a>

请求针对 EC2 上的 EMR 任务的代码修复建议：

```
Recommend code fix for my EMR-EC2 step with id s-STEP_ID on cluster j-CLUSTER_ID
```

Glue 作业的请求代码修复建议：

```
Recommend code fix for my Glue job with job run id jr_JOB_RUN_ID and job name test_job
```

# IAM 角色设置
<a name="spark-troubleshooting-agent-iam-setup"></a>

设置说明中的 CloudFormation 堆栈可自动为您设置 IAM 角色。如果您想手动执行它，请按照以下说明进行操作：

## MCP 服务器的 IAM 角色设置
<a name="iam-role-mcp-server"></a>

要访问 SMUS 托管 MCP 服务器，需要使用以下内联策略的 IAM 角色：

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowUseSagemakerUnifiedStudioMcpServer",
            "Effect": "Allow",
            "Action": [
                "sagemaker-unified-studio-mcp:InvokeMcp",
                "sagemaker-unified-studio-mcp:CallReadOnlyTool",
                "sagemaker-unified-studio-mcp:CallPrivilegedTool"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

在接下来的步骤中，我们将为此角色创建个人资料。无论哪个账户担任此角色以获取证书，都应添加到代入角色策略中。

```
{
  "Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowAccountToAssumeRole",
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::<accountId>:root" },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

## 按部署模式划分的其他权限 (emr-ec2/emr-s/Glue)
<a name="additional-permissions"></a>

### EMR-EC2 应用程序
<a name="emr-ec2-permissions"></a>

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "EMREC2ReadAccess",
            "Effect": "Allow",
            "Action": [
                "elasticmapreduce:DescribeCluster",
                "elasticmapreduce:DescribeStep",
                "elasticmapreduce:ListSteps",
                "elasticmapreduce:ListClusters",
                "elasticmapreduce:DescribeJobFlows"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "EMRS3LogAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": "*"
        },
        {
            "Sid": "EMRPersistentApp",
            "Effect": "Allow",
            "Action": [
                "elasticmapreduce:CreatePersistentAppUI",
                "elasticmapreduce:DescribePersistentAppUI",
                "elasticmapreduce:GetPersistentAppUIPresignedURL"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

### Glue Jobs
<a name="glue-permissions"></a>

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "GlueReadAccess",
            "Effect": "Allow",
            "Action": [
                "glue:GetJob",
                "glue:GetJobRun",
                "glue:GetJobRuns",
                "glue:GetJobs",
                "glue:BatchGetJobs"
            ],
            "Resource": [
                "arn:aws:glue:*:<account id>:job/*"
            ]
        },
        {
            "Sid": "GlueCloudWatchLogsAccess",
            "Effect": "Allow",
            "Action": [
                "logs:GetLogEvents",
                "logs:FilterLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:<account id>:log-group:/aws/glue/*"
            ]
        },
        {
            "Sid": "GlueSparkWebUI",
            "Effect": "Allow",
            "Action": [
                "glue:RequestLogParsing",
                "glue:GetLogParsingStatus",
                "glue:GetEnvironment",
                "glue:GetStage",
                "glue:GetStages",
                "glue:GetStageFiles",
                "glue:BatchGetStageFiles",
                "glue:GetStageAttempt",
                "glue:GetStageAttemptTaskList",
                "glue:GetStageAttemptTaskSummary",
                "glue:GetExecutors",
                "glue:GetExecutorsThreads",
                "glue:GetStorage",
                "glue:GetStorageUnit",
                "glue:GetQueries",
                "glue:GetQuery",
                "glue:GetDashboardUrl"
            ],
            "Resource": [
                "arn:aws:glue:*:<account id>:job/*"
            ]
        },
        {
            "Sid": "GluePassRoleAccess",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "iam:PassedToService": "glue.amazonaws.com"
                }
            }
        }
    ]
}
```

### EMR 无服务器应用程序
<a name="emr-serverless-permissions"></a>

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "EMRServerlessReadAccess",
            "Effect": "Allow",
            "Action": [
                "emr-serverless:GetJobRun",
                "emr-serverless:GetApplication",
                "emr-serverless:ListApplications",
                "emr-serverless:ListJobRuns",
                "emr-serverless:ListJobRunAttempts",
                "emr-serverless:GetDashboardForJobRun",
                "emr-serverless:ListTagsForResource"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "EMRServerlessCloudWatchLogsAccess",
            "Effect": "Allow",
            "Action": [
                "logs:GetLogEvents",
                "logs:FilterLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:<account id>:log-group:/aws/emr-serverless/*"
            ]
        },
        {
            "Sid": "EMRServerlessS3LogsAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": "*"
        }
    ]
}
```

### KMS 权限- CloudWatch 日志
<a name="kms-permissions"></a>

如果 CloudWatch 日志是使用 CMK 加密的，请添加以下策略，以便服务可以读取 EMR-Serverless 应用程序日志。

```
{
    "Effect": "Allow",
    "Action": [
        "kms:Decrypt",
        "kms:DescribeKey"
    ],
    "Resource": "arn:aws:kms:<region>:<account-id>:key/<cw-logs-cmk-id>"
}
```

# 使用 Spark 故障排除工具
<a name="spark-troubleshooting-agent-using-tools"></a>

## 可用的故障排除工具
<a name="available-tools"></a>

MCP 服务为 Spark 故障排除代理提供了不同的工具。主要工具如下：


| 工具名称 | 工具类别 | 说明 | 
| --- | --- | --- | 
| 分析火花工作负载 | 根本原因分析 | 为失败的 Apache Spark 工作负载提供详细的故障 | 
| spark\$1code\$1推荐 | 代码修复建议 | 为失败的作业提供 Apache Spark 代码建议 | 

# 为亚马逊 SageMaker 统一工作室 MCP 配置接口 VPC 终端节点
<a name="spark-troubleshooting-agent-vpc-endpoints"></a>

您可以通过创建接*口 VPC 终端节点在您的 VPC 和 Amazon SageMaker Unified Studio MCP 服务之间建立私有*连接。接口终端节点由 [Amazon VPC](https://aws.amazon.com/vpc/) 提供支持，这使您无需互联网网关、NAT 设备、VPN 连接或连接即可私密访问 VPC 中的 MCP 服务器。您的 VPC 中的实例不需要公有 IP 地址即可与 MCP 服务通信，并且您的 VPC 和 MCP 服务之间的流量不会离开亚马逊网络。

每个接口终端节点由您的 VPC 子网中的一个或多个[弹性网络接口](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html)表示。有关更多信息，请参阅 *Amazon VPC 用户指南中的接口 VPC* [终端节点](https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html)。

## 第 1 步：为 Amazon SageMaker Unified Studio MCP 创建接口 VPC 终端节点
<a name="create-vpc-endpoint"></a>

您可以使用亚马逊 VPC 控制台或 Amazon SageMaker Unified Studio MCP 服务创建 VPC 终端节点。 AWS CLI有关更多信息，请参阅《Amazon VPC User Guide》**中的 [Creating an interface endpoint](https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html#create-interface-endpoint)。

使用以下服务名称为 Amazon SageMaker Unified Studio MCP 创建 VPC 终端节点：
+ com.amazonaws。 *<aws-region>*。 sagemaker-unified-studio-mcp

如果您为终端节点启用私有 DNS，则可以使用该区域的默认 DNS 名称向 Amazon SageMaker Unified Studio MCP 发出 API 请求，例如，`sagemaker-unified-studio-mcp.us-east-1.api.aws`

有关更多信息，请参阅《Amazon VPC 用户指南》**中的[通过接口端点访问服务](https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html#access-service-though-endpoint)。

## 第 2 步：为 Amazon SageMaker Unified Studio MCP 创建 VPC 终端节点策略
<a name="create-vpc-endpoint-policy"></a>

您可以将终端节点策略附加到控制对 Amazon SageMaker Unified Studio MCP 的访问权限的 VPC 终端节点。该策略指定以下信息：
+ 可执行操作的主体。
+ 可执行的操作。
+ 可对其执行操作的资源。

有关更多信息，请参阅《Amazon VPC 用户指南》**中的[使用 VPC 端点控制对服务的访问](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints-access.html)。

### 示例：允许 MCP 访问特定 IAM 角色的 VPC 终端节点策略
<a name="vpc-endpoint-policy-example"></a>

以下是 Amazon SageMaker Unified Studio MCP 访问的终端节点策略示例。当关联到终端节点时，该策略允许特定 IAM 角色委托人访问所有资源上列出的 Amazon SageMaker Unified Studio MCP 操作。

```
{
  "Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::ACCOUNT-ID:role/YourRoleName"
      },
      "Action": [
        "sagemaker-unified-studio-mcp:InvokeMcp",
        "sagemaker-unified-studio-mcp:CallReadOnlyTool",
        "sagemaker-unified-studio-mcp:CallPrivilegedTool"
      ],
      "Resource": "*"
    }
  ]
}
```

## 第 3 步：测试您的 VPC
<a name="test-vpc-endpoint"></a>

该`curl`命令通过发出 HTTP/HTTPS 请求来验证 end-to-end从您的 VPC 网络 (EC2) 到 VPC 终端节点的网络连接。收到来自 MCP 服务器的消息的 curl 响应确认完整的网络路径正常运行。

### 方法 1：启用私有 DNS（推荐）
<a name="test-private-dns-enabled"></a>

```
curl https://sagemaker-unified-studio-mcp.us-east-1.api.aws/spark-troubleshooting/mcp
```

### 方法 2：未启用私有 DNS
<a name="test-private-dns-disabled"></a>

```
curl -k https://vpce-0069xxxx-ejwhxxx.sagemaker-unified-studio-mcp.us-east-1.vpce.amazonaws.com/spark-troubleshooting/mcp
```

**注意**  
由于 VPC 终端节点 DNS 名称与证书的公用名 (CN) 之间的主机名不匹配，该`-k`标志绕过 SSL 证书验证。

在这两种情况下，curl 命令都会返回响应：`{"Message":"...."}`。返回消息将验证与 MCP 服务的 VPC 终端节点的网络路径连接是否成功。

## 步骤 4：开始使用 MCP VPC 终端节点
<a name="use-vpc-endpoint"></a>

验证连接后，您可以按照步骤在中配置 MCP。[故障排除代理的设置](spark-troubleshooting-agent-setup.md)只需在 MCP 配置中使用私有 VPC 终端节点即可。

# Apache Spark 故障排除代理的跨区域处理
<a name="spark-troubleshooting-cross-region-processing"></a>

Apache Spark 故障排除代理使用跨区域推理来处理自然语言请求并生成响应。通过跨区域推理，代理会自动路由您的推理请求以优化性能，最大限度地提高可用计算资源和模型可用性，并提供最佳的客户体验。使用的跨区域推断类型取决于您运行 Apache Spark 故障排除代理的区域。在大多数区域，代理会选择您所在地理区域内的最佳区域来处理您的推理请求。但是，在某些区域，代理发出的推理请求会安全地路由到所有全球商业 AWS 区域的所有可用计算资源。

## 跨区域推理
<a name="cross-region-inference-overview"></a>

Apache Spark 故障排除代理由 Amazon Bedrock 提供支持，它使用跨区域推理将流量分配到不同的 AWS 区域，以增强大型语言模型 (LLM) 的推理性能和可靠性。

尽管跨区域推理不会改变 Spark 应用程序或故障排除体验的托管位置或数据的存储位置，但您的输入提示和输出结果可能会传输到不同的区域进行推理处理。所有数据均通过亚马逊的安全网络进行加密传输。

使用跨区域推理不会产生额外费用。

## 跨区域推理支持的区域
<a name="supported-regions-cross-region"></a>

 **使用地理跨区域推理的区域** 

对于大多数区域，跨区域推理请求保存在运行 Apache Spark 故障排除代理的同一地理 AWS 区域内。例如，美国东部（弗吉尼亚北部）地区的代理发出的请求仅发送到美国地理 AWS 区域内的区域。下表描述了您的请求可能被路由到哪些区域，具体取决于请求发出的地理位置：


| 支持的地理位置 | 推理区域 | 
| --- | --- | 
|  美国  |  美国东部（弗吉尼亚北部）（us-east-1）、美国西部（俄勒冈）（us-west-2）、美国东部（俄亥俄州）（us-east-2）、美国西部（加利福尼亚北部）（us-west-1）  | 
|  欧洲  |  欧洲（法兰克福）（eu-central-1）、欧洲（爱尔兰）（eu-west-1）、欧洲（巴黎）（eu-west-3）、欧洲（斯德哥尔摩）（eu-north-1）、欧洲（伦敦）（eu-west-2）  | 
|  亚太地区  |  亚太地区（东京）（ap-northeast-1）、亚太地区（首尔）（ap-northeast-2）、亚太地区（孟买）（ap-southeast-1）  | 

### 使用全球跨区域推理的区域
<a name="global-cross-region-inference"></a>

**重要**  
以下 AWS 区域使用全球跨区域推理。当您在这些区域使用 Apache Spark 故障排除代理时，您的请求可能会在全球范围内传输到其他 AWS 区域进行推理处理，以优化性能和可用性：  
南美洲（圣保罗）（sa-east-1）
亚太地区（新加坡）(ap-southeast-1)
亚太地区（悉尼）(ap-southeast-2)
加拿大（中部）(ca-central-1)

# 使用记录亚马逊 SageMaker 统一工作室 MCP 通话 AWS CloudTrail
<a name="spark-troubleshooting-cloudtrail-integration"></a>

Amazon SageMaker Unified Studio MCP 服务器与 AWS CloudTrail一项服务集成，该服务提供用户、角色或 AWS 服务在 Amazon SageMaker Unified Studio MCP 服务器中采取的操作的记录。 CloudTrail 将 Amazon SageMaker Unified Studio MCP 服务器的所有 API 调用捕获为事件。捕获的调用包括对 Amazon SageMaker Unified Studio MCP 服务器的调用以及在 Uni SageMaker fied Studio MCP 服务器执行工具期间对其他 AWS 操作的代码调用。如果您创建跟踪，则可以允许将 CloudTrail 事件持续传输到 Amazon S3 存储桶，包括针对 Amazon SageMaker Unified Studio MCP 服务器的事件。如果您未配置跟踪，您仍然可以在 CloudTrail 控制台的 “事件**历史记录” 中查看最新的事件**。通过收集的信息 CloudTrail，您可以确定向 Amazon SageMaker Unified Studio MCP 服务器发出的请求、发出请求的 IP 地址、谁发出了请求、何时发出请求以及其他详细信息。

要了解更多信息 CloudTrail，请参阅《[AWS CloudTrail 用户指南》](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/)。

## 中的亚马逊 SageMaker Unified Studio MCP 服务器信息 CloudTrail
<a name="sagemaker-mcp-info-in-cloudtrail"></a>

CloudTrail 在您创建 AWS 账户时已在您的账户上启用。当 Amazon SageMaker Unified Studio MCP 服务器中发生活动时，该活动会与其他 AWS 服务 CloudTrail 事件一起记录在**事件历史**记录中。您可以在自己的 AWS 账户中查看、搜索和下载最近发生的事件。有关更多信息，请参阅[使用事件历史记录查看 CloudTrail 事件](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html)。

要持续记录您的 AWS 账户中的事件，包括 SageMaker Unified Studio MCP 服务器的事件，请创建跟踪。跟踪允许 CloudTrail 将日志文件传输到 Amazon S3 存储桶。默认情况下，当您在控制台中创建跟踪时，该跟踪将应用于所有 AWS 区域。跟踪记录 AWS 分区中所有区域的事件，并将日志文件传送到您指定的 Amazon S3 存储桶。此外，您可以配置其他 AWS 服务，以进一步分析和处理 CloudTrail 日志中收集的事件数据。有关更多信息，请参阅下列内容：
+ [创建跟踪记录概述](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-create-and-update-a-trail.html)
+ [CloudTrail 支持的服务和集成](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-aws-service-specific-topics.html)
+ [配置 Amazon SNS 通知 CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/configure-sns-notifications-for-cloudtrail.html)
+ [接收来自多个区域的 CloudTrail 日志文件](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html)和[接收来自多个账户的 CloudTrail 日志文件](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-receive-logs-from-multiple-accounts.html)

在工具执行期间，所有 SageMaker Unified Studio MCP 服务器工具调用和对 AWS 服务的 API 调用都由记录。 CloudTrail例如，对不同工具的调用和从这些工具发出的 AWS 服务调用会在 CloudTrail 日志文件中生成条目。

每个事件或日志条目都包含有关生成请求的人员信息。身份信息可帮助您确定以下内容：
+ 请求是使用根用户凭证还是 IAM 用户凭证发出的。
+ 请求是使用角色还是联合用户的临时安全凭证发出的。
+ 请求是否由其他 AWS 服务发出。

有关更多信息，请参阅 [CloudTrail userIdentity 元素](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)。

## 了解亚马逊 SageMaker Unified Studio MCP 服务器日志文件条目
<a name="understanding-mcp-log-entries"></a>

跟踪是一种配置，允许将事件作为日志文件传输到您指定的 Amazon S3 存储桶。 CloudTrail 日志文件包含一个或多个日志条目。事件代表来自任何来源的单个请求，包括有关请求的操作、操作的日期和时间、请求参数等的信息。 CloudTrail 日志文件不是公共 API 调用的有序堆栈跟踪，因此它们不会按任何特定的顺序出现。

以下示例显示了演示该`CallTool`操作的 CloudTrail 日志条目。

```
{
    "eventVersion": "1.09",
    "userIdentity": {
        ...
    },
    "eventTime": "...",
    "eventSource": "sagemaker-unified-studio-mcp.amazonaws.com",
    "eventName": "CallPrivilegedTool",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "...",
    "userAgent": "...",
    "requestParameters": {
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "generate_spark_upgrade_plan",
            "arguments": "***",
            "_meta": {
                "progressToken": 1
            }
        },
        "jsonrpc": "2.0"
    },
    "responseElements": {
        "result": {
            "content": "***",
            "structuredContent": "***",
            "isError": false
        },
        "id": 1,
        "jsonrpc": "2.0"
    },
    "requestID": "12345678-1234-1234-1234-123456789012",
    "eventID": "87654321-4321-4321-4321-210987654321",
    "readOnly": false,
    "eventType": "AwsMcpEvent",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management"
}
```

以下示例显示了一个 CloudTrail 日志条目，该条目演示了调用升级工具期间来自 Amazon SageMaker Unified Studio MCP 的`AddJobFlowSteps`操作。

```
{
    "eventVersion": "1.11",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "...",
        "arn": "...",
        "accountId": "123456789012",
        "accessKeyId": "...",
        "sessionContext": {
            ...
        },
        "invokedBy": "sagemaker-unified-studio-mcp.amazonaws.com"
    },
    "eventTime": "...",
    "eventSource": "elasticmapreduce.amazonaws.com",
    "eventName": "AddJobFlowSteps",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "sagemaker-unified-studio-mcp.amazonaws.com",
    "userAgent": "sagemaker-unified-studio-mcp.amazonaws.com",
    "requestParameters": {
        "jobFlowId": "j-2PY4KXXXXXX63",
        "steps": [
            ...
        ]
    },
    "responseElements": {
        "stepIds": [
            ...
        ]
    },
    "requestID": "12345678-1234-1234-1234-123456789013",
    "eventID": "87654321-4321-4321-4321-210987654322",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "sharedEventID": "12345678-1234-1234-1234-123456789012",
    "vpcEndpointId": "sagemaker-unified-studio-mcp.amazonaws.com",
    "vpcEndpointAccountId": "sagemaker-unified-studio-mcp.amazonaws.com",
    "eventCategory": "Management"
}
```

# Apache Spark 代理的服务改进
<a name="spark-agents-service-improvements"></a>

例如，适用于 Amazon EMR 的 Apache Spark 代理可能会使用内容来帮助代理更好地回答常见问题、修复操作问题或进行调试。

## AWS 可能用于服务改进的内容
<a name="content-used-for-improvement"></a>
+ 您的自然语言提示以及来自亚马逊 EMR、 AWS Glue 和亚马逊笔记本的 Apache Spark 代理的响应 SageMaker 

## AWS 不用于服务改进的内容
<a name="content-not-used-for-improvement"></a>
+ 你自己为 Spark 应用程序编写的代码
+ SageMaker 笔记本上下文和元数据
+ 来自您的 AWS Glue 数据目录或其他数据源的数据

只有 Amazon 员工才能访问这些数据。您的信任、隐私和客户内容的安全是我们的首要任务，并可以确保我们对数据的使用符合对您的承诺。有关更多信息，请参阅 数据隐私 FAQ。

## 如何选择退出
<a name="how-to-opt-out"></a>

要选择退出 Apache Spark Agents 的数据收集，请在 Organizations for Amazon SageMaker Unified Studio MCP 服务中配置 AI 服务选择退出政策。 AWS 有关更多信息，请参阅《AWS Organizations 用户指南》**中的[人工智能服务退出政策](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_ai-opt-out.html)。

配置 AI 服务选择退出策略时，它会产生以下影响：
+ AWS 将在您选择退出（如果有）之前删除其为改善服务而收集和存储的数据。
+ 在您选择退出后， AWS 将不再收集或存储这些数据。
+ AWS 将不再使用您的内容来改善服务。

# 优化 Spark 性能
<a name="emr-spark-performance"></a>

Amazon EMR 为 Spark 提供多项性能优化功能。本主题详细介绍了各个优化功能。

有关如何设置 Spark 配置的更多信息，请参阅 [配置 Spark](emr-spark-configure.md)。

## 自适应查询执行
<a name="emr-spark-performance-aqe"></a>

自适应查询执行是一个根据运行时统计信息重新优化查询计划的框架。自 Amazon EMR 5.30.0 起，以下来自 Apache Spark 3 的自适应查询执行优化可用于 Spark 2 的 Apache Amazon EMR 运行时系统。
+ 自适应连接转换
+ 随机分区的自适应合并

**自适应连接转换**

自适应联接转换可根据查询阶段的运行时大小将 broadcast-hash-joins操作转换为 sort-merge-join操作，从而提高查询性能。 Broadcast-hash-joins当联接的一侧足够小，可以有效地向所有执行者广播其输出时，性能往往会更好，从而无需对联接的两边进行随机交换和排序。自适应联接转换扩大了 Spark 自动执行 broadcast-hash-joins的情况范围。

该功能已默认启用。可以通过将 `spark.sql.adaptive.enabled` 设置为 `false` 来禁用它，同时会禁用自适应查询执行框架。 broadcast-hash-join当其中一个 sort-merge-join联接方的运行时大小统计数据不超过（默认为 10,485,760 字节 (10 MiB)）时`spark.sql.autoBroadcastJoinThreshold`，Spark 决定将 a 转换为 a。

**随机分区的自适应合并**

随机分区的自适应合并通过合并小的连续随机分区来避免产生太多小任务的开销，从而提高查询性能。这样，您就可以预先配置更多的初始随机分区，然后在运行时将其减少到目标大小，从而提高拥有更均匀分配的随机分区的可能性。

此功能默认情况下已启用，除非 `spark.sql.shuffle.partitions` 采用显式设置。可以通过将 `spark.sql.adaptive.coalescePartitions.enabled` 设置为 `true` 来启用它。初始数量的随机分区和目标分区大小都可以分别使用 `spark.sql.adaptive.coalescePartitions.minPartitionNum` 和 `spark.sql.adaptive.advisoryPartitionSizeInBytes` 属性进行优化。有关此功能的相关 Spark 属性的详细信息，请参阅下表。


**Spark 自适应合并分区属性**  

| 属性 | 默认 值 | 说明 | 
| --- | --- | --- | 
|  `spark.sql.adaptive.coalescePartitions.enabled`  |  true，除非 `spark.sql.shuffle.partitions` 为显式设置  |  如果为 true 且 spark.sql.adaptive.enabled 为 true，则 Spark 将根据目标大小合并连续的随机分区（通过 `spark.sql.adaptive.advisoryPartitionSizeInBytes` 指定），以避免过多的小任务。  | 
|  `spark.sql.adaptive.advisoryPartitionSizeInBytes`  | 64MB |  合并时，随机分区q的指导大小（按字节计算）。此配置仅在 `spark.sql.adaptive.enabled` 和 `spark.sql.adaptive.coalescePartitions.enabled` 两者都为 `true` 时才有效。  | 
|  `spark.sql.adaptive.coalescePartitions.minPartitionNum`  | 25 |  合并后的最小随机分区数。此配置仅在 `spark.sql.adaptive.enabled` 和 `spark.sql.adaptive.coalescePartitions.enabled` 两者都为 `true` 时才有效。  | 
|  `spark.sql.adaptive.coalescePartitions.initialPartitionNum`  | 1000 |  合并前的随机分区的初始数量。此配置仅在 `spark.sql.adaptive.enabled` 和 `spark.sql.adaptive.coalescePartitions.enabled` 两者都为 `true` 时才有效。  | 

## 动态分区修剪
<a name="emr-spark-performance-dynamic"></a>

动态分区修剪通过针对特定的查询更准确地选择表中需要读取和处理的特定分区来提高作业性能。通过减少读取和处理的数据量，可节省大量的作业执行时间。对于 Amazon EMR 5.26.0，此功能已默认启用。对于 Amazon EMR 5.24.0 和 5.25.0，您可以在 Spark 中或在创建集群时，通过设置 Spark 属性 `spark.sql.dynamicPartitionPruning.enabled` 来启用此功能。


**Spark 动态分区修剪分区属性**  

| 属性 | 默认值 | 说明 | 
| --- | --- | --- | 
|  `spark.sql.dynamicPartitionPruning.enabled`  |  `true`  |  如果为 true，则启用动态分区修剪。  | 
|  `spark.sql.optimizer.dynamicPartitionPruning.enforceBroadcastReuse`  |  `true`  |  为 `true` 时，Spark 会在查询执行之前执行防御性检查，以确保动态修剪筛选条件中广播交换的重复使用不会被以后的准备规则（如用户定义的列式规则）中断。当重用被中断且此配置是 `true` 时，Spark 会删除受影响的动态修剪筛选条件，以防止发生性能和正确性问题。当动态修剪筛选条件的广播交换从相应连接操作的广播交换产生不同且不一致的结果时，可能会出现正确性问题。将此配置设置为 `false` 应谨慎执行；它允许解决如下类似场景：当用户定义的列式规则中断重用时。启用“自适应查询执行”后，将始终强制执行广播重用。  | 

这种优化功能在 Spark 2.4.2 的现有功能基础之上进行改进，只支持向下推送可以在计划时解析的静态谓词。

以下是 Spark 2.4.2 中静态谓词向下推送的示例。

```
partition_col = 5

partition_col IN (1,3,5)

partition_col between 1 and 3

partition_col = 1 + 3
```

动态分区修剪允许 Spark 引擎在运行时动态地推断哪些分区需要读取，哪些分区可以安全地消除。例如，以下查询涉及两个表：`store_sales` 表，其中包含所有店铺的全部总销售额（按区域分区）；以及 `store_regions` 表，其中包含每个国家/地区的区域映射。这些表包含有关分布于全球的存储的数据，但我们只查询北美的数据。

```
select ss.quarter, ss.region, ss.store, ss.total_sales 
from store_sales ss, store_regions sr
where ss.region = sr.region and sr.country = 'North America'
```

如果没有动态分区修剪，此查询将读取所有区域，然后过滤出与子查询的结果匹配的区域子集。使用动态分区修剪，此查询将只读取和处理子查询中返回的区域的分区。这样，通过减少数据存储和处理较少的记录，节省了时间和资源。

## 展平标量子查询
<a name="emr-spark-performance-flatten"></a>

这种优化功能通过对同一个表执行标量子查询来提高查询的性能。对于 Amazon EMR 5.26.0，此功能已默认启用。借助 Amazon EMR 5.24.0 和 5.25.0，您可以在 Spark 中或在创建集群时，通过设置 Spark 属性 `spark.sql.optimizer.flattenScalarSubqueriesWithAggregates.enabled` 来启用此功能。当此属性设置为 true 时，查询优化程序会展平使用相同关系的聚合标量子查询（如果可能）。标量子查询通过以下方法展平：将子查询中存在的任何谓词推送到聚合函数，然后执行一个聚合（针对所有聚合函数，按每个关系）。

以下示例是一个将受益于此优化的查询示例。

```
select (select avg(age) from students                    /* Subquery 1 */
                 where age between 5 and 10) as group1,
       (select avg(age) from students                    /* Subquery 2 */
                 where age between 10 and 15) as group2,
       (select avg(age) from students                    /* Subquery 3 */
                 where age between 15 and 20) as group3
```

此优化将之前的查询重写为：

```
select c1 as group1, c2 as group2, c3 as group3
from (select avg (if(age between 5 and 10, age, null)) as c1,
             avg (if(age between 10 and 15, age, null)) as c2,
             avg (if(age between 15 and 20, age, null)) as c3 from students);
```

请注意，重写的查询将只读取一次 student 表，而三个子查询的谓词将推送到 `avg` 函数中。

## DISTINCT Before INTERSECT
<a name="emr-spark-performance-distinct"></a>

这种优化可优化使用 INTERSECT 时的联接。对于 Amazon EMR 5.26.0，此功能已默认启用。借助 Amazon EMR 5.24.0 和 5.25.0，您可以在 Spark 中或在创建集群时，通过设置 Spark 属性 `spark.sql.optimizer.distinctBeforeIntersect.enabled` 来启用此功能。使用 INTERSECT 的查询会自动转换为使用左半联接。当此属性设置为 true 时，如果查询优化器检测到 DISTINCT 运算符可以将左半联接变为 a BroadcastHashJoin 而不是 a，则查询优化器会将 DISTINCT 运算符推送给 INTERSECT 的子级。 SortMergeJoin

以下示例是一个将受益于此优化的查询示例。

```
(select item.brand brand from store_sales, item
     where store_sales.item_id = item.item_id)
intersect
(select item.brand cs_brand from catalog_sales, item 
     where catalog_sales.item_id = item.item_id)
```

如果没有启用此属性 `spark.sql.optimizer.distinctBeforeIntersect.enabled`，则查询将被重写，如下所示。

```
select distinct brand from
  (select item.brand brand from store_sales, item
     where store_sales.item_id = item.item_id)
left semi join
   (select item.brand cs_brand from catalog_sales, item 
     where catalog_sales.item_id = item.item_id)
 on brand <=> cs_brand
```

当您启用此属性 `spark.sql.optimizer.distinctBeforeIntersect.enabled` 时，查询将被重写，如下所示。

```
select brand from
  (select distinct item.brand brand from store_sales, item
     where store_sales.item_id = item.item_id)
left semi join
   (select distinct item.brand cs_brand from catalog_sales, item 
     where catalog_sales.item_id = item.item_id)
 on brand <=> cs_brand
```

## Bloom 筛选条件连接
<a name="emr-spark-performance-bloom"></a>

这种优化可以通过使用从联接另一端的值生成的 [Bloom 筛选条件](https://en.wikipedia.org/wiki/Bloom_filter)对联接的一端进行预筛选，来提高部分联接的性能。对于 Amazon EMR 5.26.0，此功能已默认启用。借助 Amazon EMR 5.25.0，您可以在 Spark 中或在创建集群时，通过将 Spark 属性 `spark.sql.bloomFilterJoin.enabled` 设置为 `true` 来启用此功能。

下面是一个可以受益于 Bloom 筛选条件的示例查询。

```
select count(*)
from sales, item
where sales.item_id = item.id
and item.category in (1, 10, 16)
```

启用此功能后，Bloom 筛选条件将根据所有类别位于要查询的类别集中的项目ID构建。扫描销售表时，Bloom 筛选条件用于确定哪些销售属于肯定不在 Bloom 筛选条件定义的集中的项目。借此，可以尽早筛选出这些被标识的销售。

## 优化的连接重新排序
<a name="emr-spark-performance-join-reorder"></a>

这项优化通过将涉及带筛选条件的表的联接进行重新排序来提高查询性能。对于 Amazon EMR 5.26.0，此功能已默认启用。对于 Amazon EMR 5.25.0，您可以通过将 Spark 配置参数 `spark.sql.optimizer.sizeBasedJoinReorder.enabled` 设置为 true 来启用此功能。Spark 的默认行为是从左到右联接表，如查询中所列。此策略可能会错过首先使用筛选条件执行较小联接的机会，以便之后利用更昂贵的联接。

下面的示例查询报告了一个国家/地区所有商店的所有退回商品。如果不经过优化的联接重新排序，Spark 首先会联接两个大型表 `store_sales` 和 `store_returns`，然后将其与 `store` 联接，最终再联接 `item`。

```
select ss.item_value, sr.return_date, s.name, i.desc, 
from store_sales ss, store_returns sr, store s, item i
where ss.id = sr.id and ss.store_id = s.id and ss.item_id = i.id
and s.country = 'USA'
```

经过优化的联接重新排序，Spark 首先会联接 `store_sales` 与 `store`，因为 `store` 有一个筛选条件并且小于 `store_returns` 和 `broadcastable`。然后，Spark 会联接 `store_returns`，最后联接 `item`。如果 `item` 有一个筛选条件并且可广播，则其也符合重新排序的条件，这会使 `store_sales` 与 `store` 联接，之后联接 `item`，并在最后联接 `store_returns`。

# Spark 结果片段缓存
<a name="emr-spark-fragment-result-caching"></a>

Amazon EMR 6.6.0 及更高版本包含可选的 Spark 结果片段缓存功能，该功能可自动缓存结果片段。这些结果片段是查询子树的结果的一部分，其存储在您选择的 Amazon S3 存储桶中。存储的查询结果片段将在后续查询执行时重复使用，从而加快查询速度。

结果片段缓存分析 Spark 查询并将符合条件的结果片段缓存在指定的 S3 位置。在后续查询运行中，系统会自动检测并从 S3 中获取可用的查询结果片段。结果片段缓存不同于结果集缓存，其中，后续查询必须与原始查询完全匹配才能从缓存返回结果。当用于重复以静态数据子集为目标的查询时，结果片段缓存可显著提高性能。

请考虑以下查询，它计算 2022 年之前的订单：

```
select
    l_returnflag,
    l_linestatus,
    count(*) as count_order
from
    lineitem
where
    l_shipdate <= current_date
    and year(l_shipdate) == '2022'
group by
    l_returnflag,
    l_linestatus
```

随着时间推移，此查询需要每天运行以报告当年的总销售额。如果没有结果片段缓存，则需要每天重新计算一年中所有日期的结果。随着时间推移，查询速度会变慢，并且在年底最慢，届时将需要重新计算所有 365 天的结果。

 当您激活结果片段缓存时，将使用缓存中一年所有以前日期的结果。每天，该功能只能重新计算一天的结果。在该功能计算结果片段后，该功能将缓存片段。因此，启用缓存的查询时间很快，并且每次后续查询都保持不变。

## 启用 Spark 结果片段缓存
<a name="enable-fragment-caching"></a>

要启用 Spark 结果片段缓存，请执行以下步骤：

1. 在 Amazon S3 中创建缓存存储桶并授权 EMRFS 的 read/write 访问权限。有关更多信息，请参阅 [授予对 Amazon S3 中的 EMRFS 数据的访问权](emr-plan-credentialsprovider.md)。

1. 设置 Amazon EMR Spark 配置以启用该功能。

   ```
   spark.subResultCache.enabled = true
   spark.subResultCache.fs.root.path = s3://&example-s3-bucket;/cache_dir/
   ```

1. 为存储桶启用 S3 生命周期管理以自动清理缓存文件。

1. 或者，配置 reductionRationThreshold 和 maxBufferSize属性以进一步调整该功能。

   ```
   spark.sql.subResultCache.reductionRatioThreshold
   spark.sql.subResultCache.maxBufferSize
   ```

## 使用结果片段缓存时的注意事项
<a name="frag-caching-considerations"></a>

当您使用已缓存在 Amazon S3 中的结果而不是重新计算它们时，所节省的成本会随着使用相同缓存结果的次数而增加。对于具有大表扫描后跟筛选条件或散列聚合，并且将结果大小减少至少 8 倍（即输入大小:结果的比率至少为 8:1）的查询将从此功能受益最多。输入和结果之间的缩减率越大，成本效益就越大。只要生成结果的成本高于从 Amazon S3 获取结果的成本，缩减率较小、但在表扫描和筛选条件或聚合之间包含昂贵计算步骤的查询也将受益。默认情况下，结果片段缓存仅在检测到缩减率至少为 8:1 时才生效。

当查询重复使用缓存的结果时，此功能的好处最大。滚动和增量窗口查询就是很好的例子。例如，一个 30 天滚动窗口查询已经运行了 29 天，它只需要从其原始输入源提取 1/30 的目标数据，并将使用前 29 天的缓存结果片段。增量窗口查询将受益更多，因为窗口的开始保持固定：在每次调用查询时，需要从输入源读取的处理比例较小。

以下是使用结果片段缓存时的其他注意事项：
+ 如果查询的目标不是具有相同查询片段的相同数据，则缓存命中率较低，因此不会从此功能受益。
+ 如果查询的缩减率较低且不包含昂贵的计算步骤，则将导致缓存结果的读取开销与初始处理的开销大致相同。
+ 由于写入缓存的成本，第一个查询将始终显示较小的回归。
+ 结果片段缓存功能仅适用于 Parquet 文件。不支持其他文件格式。
+ 结果片段缓存功能缓冲区将仅尝试缓存文件拆分大小为 128 MB 或更大的扫描。在默认 Spark 配置下，如果扫描大小（正扫描的所有文件的总大小）除以执行程序内核数小于 128 MB，则结果片段缓存将被禁用。如果设置了下面所列的任何 Spark 配置，则文件拆分大小将为：

  ```
  min(maxPartitionBytes, max(openCostInBytes, scan size / minPartitionNum))
  ```
  + spark.sql。 leafNodeDefault并行度（默认值为 spark.default.parallelism）
  + spark.sql.files。 minPartitionNum （默认值为 spark.sql。 leafNodeDefault并行度）
  + spark.sql.files。 openCostIn字节
  + spark.sql.files。 maxPartitionBytes
+ 结果片段缓存功能以 RDD 分区粒度缓存。前面描述的默认 8:1 缩减率是按每个 RDD 分区评估的。与每 RDD 缩减率始终低于 8:1 的工作负载相比，每 RDD 缩减率大于和低于 8:1 的工作负载的性能优势可能更小。
+ 默认情况下，结果片段缓存功能对缓存的每个 RDD 分区使用 16MB 写入缓冲区。如果每个 RDD 分区的缓存超过 16MB，则确定无法进行写入的成本可能会导致性能下降。
+ 默认情况下，结果片段缓存不会尝试缓存缩减率小于 8:1 的 RDD 分区结果，并将写入缓冲区限制为 16MB，但这两个值都可以通过以下配置进行调整：

  ```
  spark.sql.subResultCache.reductionRatioThreshold (default: 8.0)
  spark.sql.subResultCache.maxBufferSize (default: 16MB, max: 64MB)
  ```
+ 使用相同 Amazon EMR 发行版的多个集群可以共享同一个缓存位置。为了确保结果的正确性，结果片段缓存将不使用不同发行版的 Amazon EMR 写入的缓存结果。
+ 对于 Spark Streaming 用例或使用 Apache Ranger 或时 RecordServer，结果片段缓存将自动禁用。 AWS Lake Formation 
+ 结果片段缓存 read/writes 使用 EMRFS/S3A 和 Amazon S3 存储桶。支持 CSE（仅限 EMRFS）/SSE S3/SSE KMS 加密。就上下文而言，S3A 提供了一个 Hadoop 实现，使集群能够在 Amazon S3 中读取和写入数据。请注意，EMR-7.4.0 及更高版本支持 S3A。

# 使用 Nvidia RAPIDS Accelerator for Apache Spark
<a name="emr-spark-rapids"></a>

对于 Amazon EMR 发行版 6.2.0 及更高版本，您可以使用 Nvidia 的 [RAPIDS Accelerator for Apache Spark](https://docs.nvidia.com/spark-rapids/user-guide/latest/overview.html) 插件来通过 EC2 图形处理器（GPU）实例类型加速 Spark。RAPIDS Accelerator 将通过 GPU 加速您的 Apache Spark 3.0 数据科学管道，无需更改代码，并将加快数据处理和模型训练，同时大幅降低基础设施成本。

以下部分将引导您完成配置 EMR 集群来使用 Spark-RAPIDS Plugin for Spark。

## 选择实例类型
<a name="emr-spark-rapids-instancetypes"></a>

要将 Nvidia Spark-RAPIDS 插件用于 Spark，核心实例组和任务实例组必须使用符合 Spark-RAPIDS 的[硬件要求](https://nvidia.github.io/spark-rapids/)的 EC2 GPU 实例类型。要查看 Amazon EMR 支持的 GPU 实例类型的完整列表，请参阅《Amazon EMR 管理指南》**中的[支持的实例类型](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-supported-instance-types.html)。主实例组的实例类型可以是 GPU 或非 GPU 类型，但不支持 ARM 实例类型。

## 为集群设置应用程序配置
<a name="emr-spark-rapids-appconfig"></a>

**1。使 Amazon EMR 能在您的新集群上安装插件**

要安装插件，请在创建集群时提供以下配置：

```
{
	"Classification":"spark",
	"Properties":{
		"enableSparkRapids":"true"
	}
}
```

**2。将 YARN 配置为使用 GPU**

有关如何在 YARN 上使用 GPU 的详细信息，请参阅 Apache Hadoop 文档中的[在 YARN 上使用 GPU](https://hadoop.apache.org/docs/r3.2.1/hadoop-yarn/hadoop-yarn-site/UsingGpus.html)。以下示例显示了 Amazon EMR 6.x 和 7.x 发行版的 YARN 配置示例：

------
#### [ Amazon EMR 7.x ]

**Amazon EMR 7.x 的 YARN 配置示例**

```
{
    "Classification":"yarn-site",
    "Properties":{
        "yarn.nodemanager.resource-plugins":"yarn.io/gpu",
        "yarn.resource-types":"yarn.io/gpu",
        "yarn.nodemanager.resource-plugins.gpu.allowed-gpu-devices":"auto",
        "yarn.nodemanager.resource-plugins.gpu.path-to-discovery-executables":"/usr/bin",
        "yarn.nodemanager.linux-container-executor.cgroups.mount":"true",
        "yarn.nodemanager.linux-container-executor.cgroups.mount-path":"/spark-rapids-cgroup",
        "yarn.nodemanager.linux-container-executor.cgroups.hierarchy":"yarn",
        "yarn.nodemanager.container-executor.class":"org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor"
    }
},{
    "Classification":"container-executor",
    "Properties":{
        
    },
    "Configurations":[
        {
            "Classification":"gpu",
            "Properties":{
                "module.enabled":"true"
            }
        },
        {
            "Classification":"cgroups",
            "Properties":{
                "root":"/spark-rapids-cgroup",
                "yarn-hierarchy":"yarn"
            }
        }
    ]
}
```

------
#### [ Amazon EMR 6.x ]

**Amazon EMR 6.x 的 YARN 配置示例**

```
{
    "Classification":"yarn-site",
    "Properties":{
        "yarn.nodemanager.resource-plugins":"yarn.io/gpu",
        "yarn.resource-types":"yarn.io/gpu",
        "yarn.nodemanager.resource-plugins.gpu.allowed-gpu-devices":"auto",
        "yarn.nodemanager.resource-plugins.gpu.path-to-discovery-executables":"/usr/bin",
        "yarn.nodemanager.linux-container-executor.cgroups.mount":"true",
        "yarn.nodemanager.linux-container-executor.cgroups.mount-path":"/sys/fs/cgroup",
        "yarn.nodemanager.linux-container-executor.cgroups.hierarchy":"yarn",
        "yarn.nodemanager.container-executor.class":"org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor"
    }
},{
    "Classification":"container-executor",
    "Properties":{
        
    },
    "Configurations":[
        {
            "Classification":"gpu",
            "Properties":{
                "module.enabled":"true"
            }
        },
        {
            "Classification":"cgroups",
            "Properties":{
                "root":"/sys/fs/cgroup",
                "yarn-hierarchy":"yarn"
            }
        }
    ]
}
```

------

**3。将 Spark 配置为使用 RAPIDS**

以下是使 Spark 能够使用 RAPIDS 插件所需的配置：

```
{
	"Classification":"spark-defaults",
	"Properties":{
		"spark.plugins":"com.nvidia.spark.SQLPlugin",
		"spark.executor.resource.gpu.discoveryScript":"/usr/lib/spark/scripts/gpu/getGpusResources.sh",
		"spark.executor.extraLibraryPath":"/usr/local/cuda/targets/x86_64-linux/lib:/usr/local/cuda/extras/CUPTI/lib64:/usr/local/cuda/compat/lib:/usr/local/cuda/lib:/usr/local/cuda/lib64:/usr/lib/hadoop/lib/native:/usr/lib/hadoop-lzo/lib/native:/docker/usr/lib/hadoop/lib/native:/docker/usr/lib/hadoop-lzo/lib/native"
	}
}
```

XGBoost4在集群上启用 [Spark RAPIDS 插件后， XGBoost 文档中的 J-Spark 库](https://xgboost.readthedocs.io/en/latest/jvm/xgboost4j_spark_tutorial.html)也可用。您可以使用以下配置 XGBoost 与您的 Spark 作业集成：

```
{
	"Classification":"spark-defaults",
	"Properties":{
		"spark.submit.pyFiles":"/usr/lib/spark/jars/xgboost4j-spark_3.0-1.4.2-0.3.0.jar"
	}
}
```

有关可用于优化 GPU 加速的 EMR 集群的其他 Spark 配置，请参阅 Nvidia.github.io 文档中的 [RAPIDS Accelerator for Apache Spark Tuning Guide](https://docs.nvidia.com/spark-rapids/user-guide/latest/tuning-guide.html)。

**4。配置 YARN 容量调度器**

必须配置 `DominantResourceCalculator` 来启用 GPU 调度和隔离。有关详细信息，请参阅 Apache Hadoop 文档中的 [Using GPU On YARN](https://hadoop.apache.org/docs/r3.2.1/hadoop-yarn/hadoop-yarn-site/UsingGpus.html)。

```
{
	"Classification":"capacity-scheduler",
	"Properties":{
		"yarn.scheduler.capacity.resource-calculator":"org.apache.hadoop.yarn.util.resource.DominantResourceCalculator"
	}
}
```

**5。创建一个 JSON 文件以包含您的配置**

您可以创建一个 JSON 文件，在其中包含您的配置，以便为 Spark 集群使用 RAPIDS 插件。您稍后在启动集群时需提供该文件。

您可以将文件存储在本地或 S3 上。有关如何为集群提供应用程序配置的详细信息，请参阅[配置应用程序](emr-configure-apps.md)。

使用以下示例文件作为模板来构建自己的配置。

------
#### [ Amazon EMR 7.x ]

**Amazon EMR 7.x 的示例 `my-configurations.json` 文件**

```
[
    {
        "Classification":"spark",
        "Properties":{
            "enableSparkRapids":"true"
        }
    },
    {
        "Classification":"yarn-site",
        "Properties":{
            "yarn.nodemanager.resource-plugins":"yarn.io/gpu",
            "yarn.resource-types":"yarn.io/gpu",
            "yarn.nodemanager.resource-plugins.gpu.allowed-gpu-devices":"auto",
            "yarn.nodemanager.resource-plugins.gpu.path-to-discovery-executables":"/usr/bin",
            "yarn.nodemanager.linux-container-executor.cgroups.mount":"true",
            "yarn.nodemanager.linux-container-executor.cgroups.mount-path":"/spark-rapids-cgroup",
            "yarn.nodemanager.linux-container-executor.cgroups.hierarchy":"yarn",
            "yarn.nodemanager.container-executor.class":"org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor"
        }
    },
    {
        "Classification":"container-executor",
        "Properties":{
            
        },
        "Configurations":[
            {
                "Classification":"gpu",
                "Properties":{
                    "module.enabled":"true"
                }
            },
            {
                "Classification":"cgroups",
                "Properties":{
                    "root":"/spark-rapids-cgroup",
                    "yarn-hierarchy":"yarn"
                }
            }
        ]
    },
    {
        "Classification":"spark-defaults",
        "Properties":{
            "spark.plugins":"com.nvidia.spark.SQLPlugin",
            "spark.executor.resource.gpu.discoveryScript":"/usr/lib/spark/scripts/gpu/getGpusResources.sh",
            "spark.executor.extraLibraryPath":"/usr/local/cuda/targets/x86_64-linux/lib:/usr/local/cuda/extras/CUPTI/lib64:/usr/local/cuda/compat/lib:/usr/local/cuda/lib:/usr/local/cuda/lib64:/usr/lib/hadoop/lib/native:/usr/lib/hadoop-lzo/lib/native:/docker/usr/lib/hadoop/lib/native:/docker/usr/lib/hadoop-lzo/lib/native",
            "spark.submit.pyFiles":"/usr/lib/spark/jars/xgboost4j-spark_3.0-1.4.2-0.3.0.jar",
            "spark.rapids.sql.concurrentGpuTasks":"1",
            "spark.executor.resource.gpu.amount":"1",
            "spark.executor.cores":"2",
            "spark.task.cpus":"1",
            "spark.task.resource.gpu.amount":"0.5",
            "spark.rapids.memory.pinnedPool.size":"0",
            "spark.executor.memoryOverhead":"2G",
            "spark.locality.wait":"0s",
            "spark.sql.shuffle.partitions":"200",
            "spark.sql.files.maxPartitionBytes":"512m"
        }
    },
    {
        "Classification":"capacity-scheduler",
        "Properties":{
            "yarn.scheduler.capacity.resource-calculator":"org.apache.hadoop.yarn.util.resource.DominantResourceCalculator"
        }
    }
]
```

------
#### [ Amazon EMR 6.x ]

**Amazon EMR 6.x 的示例 `my-configurations.json` 文件**

```
[
    {
        "Classification":"spark",
        "Properties":{
            "enableSparkRapids":"true"
        }
    },
    {
        "Classification":"yarn-site",
        "Properties":{
            "yarn.nodemanager.resource-plugins":"yarn.io/gpu",
            "yarn.resource-types":"yarn.io/gpu",
            "yarn.nodemanager.resource-plugins.gpu.allowed-gpu-devices":"auto",
            "yarn.nodemanager.resource-plugins.gpu.path-to-discovery-executables":"/usr/bin",
            "yarn.nodemanager.linux-container-executor.cgroups.mount":"true",
            "yarn.nodemanager.linux-container-executor.cgroups.mount-path":"/sys/fs/cgroup",
            "yarn.nodemanager.linux-container-executor.cgroups.hierarchy":"yarn",
            "yarn.nodemanager.container-executor.class":"org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor"
        }
    },
    {
        "Classification":"container-executor",
        "Properties":{
            
        },
        "Configurations":[
            {
                "Classification":"gpu",
                "Properties":{
                    "module.enabled":"true"
                }
            },
            {
                "Classification":"cgroups",
                "Properties":{
                    "root":"/sys/fs/cgroup",
                    "yarn-hierarchy":"yarn"
                }
            }
        ]
    },
    {
        "Classification":"spark-defaults",
        "Properties":{
            "spark.plugins":"com.nvidia.spark.SQLPlugin",
            "spark.executor.resource.gpu.discoveryScript":"/usr/lib/spark/scripts/gpu/getGpusResources.sh",
            "spark.executor.extraLibraryPath":"/usr/local/cuda/targets/x86_64-linux/lib:/usr/local/cuda/extras/CUPTI/lib64:/usr/local/cuda/compat/lib:/usr/local/cuda/lib:/usr/local/cuda/lib64:/usr/lib/hadoop/lib/native:/usr/lib/hadoop-lzo/lib/native:/docker/usr/lib/hadoop/lib/native:/docker/usr/lib/hadoop-lzo/lib/native",
            "spark.submit.pyFiles":"/usr/lib/spark/jars/xgboost4j-spark_3.0-1.4.2-0.3.0.jar",
            "spark.rapids.sql.concurrentGpuTasks":"1",
            "spark.executor.resource.gpu.amount":"1",
            "spark.executor.cores":"2",
            "spark.task.cpus":"1",
            "spark.task.resource.gpu.amount":"0.5",
            "spark.rapids.memory.pinnedPool.size":"0",
            "spark.executor.memoryOverhead":"2G",
            "spark.locality.wait":"0s",
            "spark.sql.shuffle.partitions":"200",
            "spark.sql.files.maxPartitionBytes":"512m"
        }
    },
    {
        "Classification":"capacity-scheduler",
        "Properties":{
            "yarn.scheduler.capacity.resource-calculator":"org.apache.hadoop.yarn.util.resource.DominantResourceCalculator"
        }
    }
]
```

------

## 为您的集群添加引导操作
<a name="emr-spark-rapids-bootstrap"></a>

有关如何在创建集群时提供引导操作脚本的更多信息，请参阅《Amazon EMR 管理指南》**中的[引导操作基础](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-bootstrap.html#bootstrapUses)。

以下示例脚本展示了如何为 Amazon EMR 6.x 和 7.x 制作引导操作文件：

------
#### [ Amazon EMR 7.x ]

**Amazon EMR 7.x 的示例 `my-bootstrap-action.sh` 文件**

要使用 YARN 管理 Amazon EMR 7.x 发行版的 GPU 资源，您必须在集群上手动挂载 CGroup v1。您可以使用引导操作脚本来执行此操作，如本示例所示。

```
#!/bin/bash
set -ex
 
sudo mkdir -p /spark-rapids-cgroup/devices
sudo mount -t cgroup -o devices cgroupv1-devices /spark-rapids-cgroup/devices
sudo chmod a+rwx -R /spark-rapids-cgroup
```

------
#### [ Amazon EMR 6.x ]

**Amazon EMR 6.x 的示例 `my-bootstrap-action.sh` 文件**

对于 Amazon EMR 6.x 发行版，您必须在集群上打开 YARN 的 CGroup 权限。您可以使用引导操作脚本来执行此操作，如本示例所示。

```
#!/bin/bash
set -ex
 
sudo chmod a+rwx -R /sys/fs/cgroup/cpu,cpuacct
sudo chmod a+rwx -R /sys/fs/cgroup/devices
```

------

## 启动您的集群。
<a name="emr-spark-rapids-launchcluster"></a>

最后一步是使用上述集群配置启动您的集群。以下是一个通过 Amazon EMR CLI 启动集群的命令示例：

```
 aws emr create-cluster \
--release-label emr-7.12.0 \
--applications Name=Hadoop Name=Spark \
--service-role EMR_DefaultRole_V2 \
--ec2-attributes KeyName=my-key-pair,InstanceProfile=EMR_EC2_DefaultRole \
--instance-groups InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m4.4xlarge \                 
                  InstanceGroupType=CORE,InstanceCount=1,InstanceType=g4dn.2xlarge \    
                  InstanceGroupType=TASK,InstanceCount=1,InstanceType=g4dn.2xlarge \
--configurations file:///my-configurations.json \
--bootstrap-actions Name='My Spark Rapids Bootstrap action',Path=s3://amzn-s3-demo-bucket/my-bootstrap-action.sh
```

# 访问 Spark Shell
<a name="emr-spark-shell"></a>

Spark Shell 基于 Scala REPL (Read-Eval-Print-Loop)。它让您能够以交互方式创建 Spark 程序并将工作提交到框架。您可以通过 SSH 连接主节点并调用 `spark-shell`，从而访问 Spark Shell。有关如何连接到主节点的更多信息，请参阅《Amazon EMR 管理指南**》中的[使用 SSH 连接到主节点](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)。以下示例使用存储在 Amazon S3 中的 Apache HTTP Server 访问日志。

**注意**  
这些示例中的存储桶对能够访问美国东部（弗吉尼亚州北部）的客户端可用。

 默认情况下，Spark 外壳会创建自己的名为的[SparkContext](https://spark.apache.org/docs/1.3.1/api/scala/index.html#org.apache.spark.SparkContext)对象`sc`。如果 REPL 中需要此上下文，则可以使用此上下文。 sqlContext也有外壳可供选择，它是 [HiveContext](https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.hive.HiveContext).

**Example 使用 Spark Shell 统计存储在 Amazon S3 中的某个文件中的某个字符串的出现次数**  
本示例使用 `sc` 读取存储在 Amazon S3 中的文本文件。  

```
scala> sc
res0: org.apache.spark.SparkContext = org.apache.spark.SparkContext@404721db

scala> val textFile = sc.textFile("s3://elasticmapreduce/samples/hive-ads/tables/impressions/dt=2009-04-13-08-05/ec2-0-51-75-39.amazon.com.rproxy.govskope.us-2009-04-13-08-05.log")
```
Spark 创建 textFile 及关联的[数据结构](https://spark.apache.org/docs/latest/programming-guide.html#resilient-distributed-datasets-rdds)。然后，示例会统计此日志文件中包含字符串“cartoonnetwork.com”的行数：  

```
scala> val linesWithCartoonNetwork = textFile.filter(line => line.contains("cartoonnetwork.com")).count()
linesWithCartoonNetwork: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[2] at filter at <console>:23
<snip>
<Spark program runs>
scala> linesWithCartoonNetwork
res2: Long = 9
```

**Example 使用基于 Python 的 Spark Shell 统计存储在 Amazon S3 中的某个文件中的某个字符串的出现次数**  
Spark 还包含一个基于 Python 的 Shell `pyspark`，您可以用它来设计以 Python 编写的 Spark 程序的原型。就像在主节点`pyspark`上调用一样；它也有相同的[SparkContext](https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.SparkContext.html#pyspark.SparkContext)对象。`spark-shell`  

```
>>> sc
<pyspark.context.SparkContext object at 0x7fe7e659fa50>
>>> textfile = sc.textFile("s3://elasticmapreduce/samples/hive-ads/tables/impressions/dt=2009-04-13-08-05/ec2-0-51-75-39.amazon.com.rproxy.govskope.us-2009-04-13-08-05.log")
```
Spark 创建 textFile 及关联的[数据结构](https://spark.apache.org/docs/latest/programming-guide.html#resilient-distributed-datasets-rdds)。然后，示例会统计此日志文件中包含字符串“cartoonnetwork.com”的行数。  

```
>>> linesWithCartoonNetwork = textfile.filter(lambda line: "cartoonnetwork.com" in line).count()
15/06/04 17:12:22 INFO lzo.GPLNativeCodeLoader: Loaded native gpl library from the embedded binaries
15/06/04 17:12:22 INFO lzo.LzoCodec: Successfully loaded & initialized native-lzo library [hadoop-lzo rev EXAMPLE]
15/06/04 17:12:23 INFO fs.EmrFileSystem: Consistency disabled, using com.amazon.ws.emr.hadoop.fs.s3n.S3NativeFileSystem as filesystem implementation
<snip>
<Spark program continues>
>>> linesWithCartoonNetwork
9
```

# 使用 Amazon SageMaker Spark 进行机器学习
<a name="emr-spark-sagemaker"></a>

当使用 Amazon EMR 发行版 5.11.0 及更高版本时，`aws-sagemaker-spark-sdk` 组件将随 Spark 一起安装。此组件安装 Amazon SageMaker Spark 和相关依赖项，以便将 Spark 与[亚马逊](https://aws.amazon.com/sagemaker/)集成 SageMaker。请注意，Amazon EMR 7.x 及更高版本不提供 `aws-sagemaker-spark-sdk` 组件。你可以使用 Amazon SageMaker Spark 通过亚马逊 SageMaker 阶段构建 Spark 机器学习 (ML) 管道。有关更多信息，请参阅亚马逊* SageMaker 开发者指南中的[亚马逊 SageMaker Spark 自述文件](https://github.com/aws/sagemaker-spark/blob/master/README.md) GitHub 和 SageMaker在亚马逊*[上使用 Apache Spark](https://docs.aws.amazon.com/sagemaker/latest/dg/apache-spark.html)。

# 编写 Spark 应用程序
<a name="emr-spark-application"></a>

[可使用 Scala、Java 或 Python 来编写 Spark 应用程序。](https://aws.amazon.com/big-data/what-is-spark/)Apache Spark 文档的 [Spark 示例](https://spark.apache.org/examples.html)主题包含多个 Spark 应用程序示例。下面所示为三个内在支持的应用程序中的 Estimating Pi 示例。您还可以在`$SPARK_HOME/examples`和中查看完整的示例[GitHub](https://github.com/apache/spark/tree/master/examples/src/main)。有关如何为 Spark 编译 JARs 的更多信息，请参阅 Apache Spark 文档中的[快速入门](https://spark.apache.org/docs/latest/quick-start.html)主题。

## Scala
<a name="emr-spark-application-scala"></a>

为避免发生 Scala 兼容性问题，建议您在为 Amazon EMR 集群编译 Spark 应用程序时使用正确的 Scala 版本的 Spark 依赖项。您应该使用的 Scala 版本取决于您的集群上安装的 Spark 版本。例如，Amazon EMR 发行版 5.30.1 使用 Spark 2.4.5，该版本是使用 Scala 2.11 构建的。如果您的集群使用 Amazon EMR 发行版 5.30.1，请使用 Scala 2.11 的 Spark 依赖项。有关 Spark 使用的 Scala 版本的更多信息，请参阅 [Apache Spark 文档](https://spark.apache.org/documentation.html)

```
package org.apache.spark.examples
import scala.math.random
import org.apache.spark._

/** Computes an approximation to pi */
object SparkPi {
  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("Spark Pi")
    val spark = new SparkContext(conf)
    val slices = if (args.length > 0) args(0).toInt else 2
    val n = math.min(100000L * slices, Int.MaxValue).toInt // avoid overflow
    val count = spark.parallelize(1 until n, slices).map { i =>
      val x = random * 2 - 1
      val y = random * 2 - 1
      if (x*x + y*y < 1) 1 else 0
    }.reduce(_ + _)
    println("Pi is roughly " + 4.0 * count / n)
    spark.stop()
  }
}
```

## Java
<a name="emr-spark-application-java"></a>

```
package org.apache.spark.examples;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.Function2;

import java.util.ArrayList;
import java.util.List;

/** 
 * Computes an approximation to pi
 * Usage: JavaSparkPi [slices]
 */
public final class JavaSparkPi {

  public static void main(String[] args) throws Exception {
    SparkConf sparkConf = new SparkConf().setAppName("JavaSparkPi");
    JavaSparkContext jsc = new JavaSparkContext(sparkConf);

    int slices = (args.length == 1) ? Integer.parseInt(args[0]) : 2;
    int n = 100000 * slices;
    List<Integer> l = new ArrayList<Integer>(n);
    for (int i = 0; i < n; i++) {
      l.add(i);
    }

    JavaRDD<Integer> dataSet = jsc.parallelize(l, slices);

    int count = dataSet.map(new Function<Integer, Integer>() {
      @Override
      public Integer call(Integer integer) {
        double x = Math.random() * 2 - 1;
        double y = Math.random() * 2 - 1;
        return (x * x + y * y < 1) ? 1 : 0;
      }
    }).reduce(new Function2<Integer, Integer, Integer>() {
      @Override
      public Integer call(Integer integer, Integer integer2) {
        return integer + integer2;
      }
    });

    System.out.println("Pi is roughly " + 4.0 * count / n);

    jsc.stop();
  }
}
```

## Python
<a name="emr-spark-application-spark27"></a>

```
import argparse
import logging
from operator import add
from random import random

from pyspark.sql import SparkSession

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")


def calculate_pi(partitions, output_uri):
    """
    Calculates pi by testing a large number of random numbers against a unit circle
    inscribed inside a square. The trials are partitioned so they can be run in
    parallel on cluster instances.

    :param partitions: The number of partitions to use for the calculation.
    :param output_uri: The URI where the output is written, typically an Amazon S3
                       bucket, such as 's3://example-bucket/pi-calc'.
    """

    def calculate_hit(_):
        x = random() * 2 - 1
        y = random() * 2 - 1
        return 1 if x**2 + y**2 < 1 else 0

    tries = 100000 * partitions
    logger.info(
        "Calculating pi with a total of %s tries in %s partitions.", tries, partitions
    )
    with SparkSession.builder.appName("My PyPi").getOrCreate() as spark:
        hits = (
            spark.sparkContext.parallelize(range(tries), partitions)
            .map(calculate_hit)
            .reduce(add)
        )
        pi = 4.0 * hits / tries
        logger.info("%s tries and %s hits gives pi estimate of %s.", tries, hits, pi)
        if output_uri is not None:
            df = spark.createDataFrame([(tries, hits, pi)], ["tries", "hits", "pi"])
            df.write.mode("overwrite").json(output_uri)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--partitions",
        default=2,
        type=int,
        help="The number of parallel partitions to use when calculating pi.",
    )
    parser.add_argument(
        "--output_uri", help="The URI where output is saved, typically an S3 bucket."
    )
    args = parser.parse_args()

    calculate_pi(args.partitions, args.output_uri)
```

# 使用 Amazon S3 提高 Spark 性能
<a name="emr-spark-s3-performance"></a>

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

[S3 Select](https://aws.amazon.com/blogs/aws/s3-glacier-select/) 可通过将处理“向下推送”到 Amazon S3 来提高某些应用程序中 CSV 和 JSON 文件的查询性能。

EMRFS S3 优化的提交者是该类的替代方案，该[OutputCommitter](https://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapreduce/OutputCommitter.html)类使用 EMRFS 的分段上传功能来提高使用 Spark、和数据集将 Parquet 文件写入 Amazon S3 时的性能。 DataFrames

**Topics**
+ [将 S3 Select 与 Spark 结合使用以提高查询性能](emr-spark-s3select.md)
+ [EMR Spark MagicCommitProtocol](emr-spark-magic-commit-protocol.md)
+ [使用经 EMRFS S3 优化的提交程序](emr-spark-s3-optimized-committer.md)
+ [使用经 EMRFS S3 优化的提交协议](emr-spark-s3-optimized-commit-protocol.md)
+ [使用 EMRFS 重试 Amazon S3 请求](emr-spark-emrfs-retry.md)

# 将 S3 Select 与 Spark 结合使用以提高查询性能
<a name="emr-spark-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.17.0 及更高版本中，您可以将 [S3 Select](https://aws.amazon.com/blogs/aws/s3-glacier-select/) 与 Amazon EMR 上的 Spark 结合使用。*S3 Select* 可让应用程序仅从对象检索数据子集。对于 Amazon EMR，筛选要处理的大型数据集的计算工作是从集群“向下推送”到 Amazon S3，这可以在某些应用程序中提高性能和减少 Amazon EMR 与 Amazon S3 之间传输的数据量。

S3 Select 支持使用 `s3selectCSV` 和 `s3selectJSON` 值来指定数据格式的 CSV 和 JSON 文件。有关更多信息以及示例，请参阅 [在代码中指定 S3 Select](#emr-spark-s3select-specify)。

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

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

使用以下准则来确定您的应用程序是否为使用 S3 Select 的候选项：
+ 您的查询将筛选掉原始数据集的一半以上的数据。
+ 您在 Amazon S3 和 Amazon EMR 集群之间的网络连接具有良好的传输速度和可用带宽。Amazon S3 不压缩 HTTP 响应，因此响应大小可能会根据压缩的输入文件而增大。

## 注意事项和限制
<a name="emr-spark-s3select-considerations"></a>
+ 使用客户提供的加密密钥进行的 Amazon S3 服务器端加密（SSE-C）与客户端加密都不受支持。
+ 不支持 `AllowQuotedRecordDelimiters` 属性。如果指定该属性，则查询将失败。
+ 仅支持采用 UTF-8 格式的 CSV 和 JSON 文件。不支持 CSVs多行。
+ 仅支持未压缩文件或 gzip 文件。
+ 不支持 Spark CSV 和 JSON 选项（如 `nanValue`、`positiveInf`、`negativeInf`）以及与损坏记录相关的选项（例如，failfast 和 dropmalformed 模式）。
+ 不支持在十进制数中使用逗号 (,)。例如，不支持 `10,000`，支持 `10000`。
+ 不支持最后一行中的注释字符。
+ 文件末尾的空行不会被处理。
+ 以下筛选条件不会向下推送到 Amazon S3：
  + 聚合函数（如 `COUNT()` 和 `SUM()`）。
  + 对属性进行 `CAST()` 的筛选条件。例如 `CAST(stringColumn as INT) = 1`。
  + 具有作为对象或很复杂的属性的筛选条件。例如 `intArray[1] = 1, objectColumn.objectNumber = 1`。
  + 值不是文本值的筛选条件。例如，`intColumn1 = intColumn2`
  + 仅支持 [S3 Select 支持的数据类型](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-glacier-select-sql-reference-data-types.html)，但存在记录的限制。

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

以下示例演示如何使用 Scala、SQL、R 和 PySpark为 CSV 指定 S3 Select。您可以通过同样的方法使用适用于 JSON 的 S3 Select。有关选项、默认值和限制的列表，请参阅[选项](#emr-spark-s3select-specify-options)。

------
#### [ PySpark ]

```
spark
  .read
  .format("s3selectCSV") // "s3selectJson" for Json
  .schema(...) // optional, but recommended
  .options(...) // optional
  .load("s3://path/to/my/datafiles")
```

------
#### [ R ]

```
read.df("s3://path/to/my/datafiles", "s3selectCSV", schema, header = "true", delimiter = "\t")
```

------
#### [ Scala ]

```
spark
  .read
  .format("s3selectCSV") // "s3selectJson" for Json
  .schema(...) // optional, but recommended
  .options(...) // optional. Examples:  
  // .options(Map("quote" -> "\'", "header" -> "true")) or
  // .option("quote", "\'").option("header", "true")
  .load("s3://path/to/my/datafiles")
```

------
#### [ SQL ]

```
CREATE TEMPORARY VIEW MyView (number INT, name STRING) USING s3selectCSV OPTIONS (path "s3://path/to/my/datafiles", header "true", delimiter "\t")
```

------

### 选项
<a name="emr-spark-s3select-specify-options"></a>

使用 `s3selectCSV` 和 `s3selectJSON` 时，有以下选项可用。如果未指定，将使用默认值。

#### 使用 S3selectCSV 时的选项
<a name="emr-spark-s3select-specify-options-csv"></a>


| Option | 默认 | 用法 | 
| --- | --- | --- | 
|  `compression`  |  `"none"`  |  指示是否使用了压缩。`"gzip"` 是除 `"none"` 之外唯一受支持的设置。  | 
|  `delimiter`  |  ","  |  指定字段分隔符。  | 
|  `quote`  |  `'\"'`  |  指定引号字符。不支持指定空字符串，这样做会导致 XML 格式不正确错误。  | 
|  `escape`  |  `'\\'`  |  指定转义字符。  | 
|  `header`  |  `"false"`  |  `"false"` 指定不存在标头。`"true"` 指定第一行中存在标头。仅支持第一行中的标头，不支持标头前面的空行。  | 
|  comment  |  `"#"`  |  指定注释字符。无法禁用注释标记。换句话说，不支持值 `\u0000`。  | 
|  `nullValue`  |  ""  |    | 

#### 使用 S3selectJSON 时的选项
<a name="emr-spark-s3select-specify-options-json"></a>


| Option | 默认 | 用法 | 
| --- | --- | --- | 
|  `compression`  |  `"none"`  |  指示是否使用了压缩。`"gzip"` 是除 `"none"` 之外唯一受支持的设置。  | 
|  `multiline`  |  “false”  |  `"false"` 指定 JSON 采用 S3 Select `LINES` 格式，这意味着输入数据中的每个行都包含单个 JSON 对象。`"true"` 指定 JSON 采用 S3 Select `DOCUMENT` 格式，这意味着 JSON 对象可跨输入数据中的多个行。  | 

# EMR Spark MagicCommitProtocol
<a name="emr-spark-magic-commit-protocol"></a>

从 EMR 6.15.0 起，在使用 S3A 文件系统时，它将 MagicCommitProtocol 成为 Spark FileCommitProtocol 的默认设置。

## MagicCommitProtocol
<a name="magic-commit-protocol"></a>

 MagicCommitProtocol 是的另一种实现方式 [FileCommitProtocol](https://dlcdn.apache.org/spark/docs/2.4.2/api/java/org/apache/spark/internal/io/FileCommitProtocol.html)，针对在使用 S3A 文件系统时使用 EMR Spark 将文件写入 Amazon S3 进行了优化。此协议旨在通过避免在作业和任务提交阶段使用 Amazon S3 中的重命名操作来提高应用程序性能。

 MagicCommitProtocol 这是 Spark 在使用 S3A 文件系统时在 Amazon Elastic Map Reduce (EMR) 上运行时使用的默认 FileCommitProtocol 实现。 MagicCommitProtocol 内部使用 [magicv2Committer 来执行向](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/s3a-magicv2-committer.html) Amazon S3 写入文件。

对于静态插入操作，会在任务提交阶段将文件 MagicCommitProtocol 写入作业的输出位置。相比之下，对于动态插入覆盖操作，任务尝试写入的文件只有在作业提交时才会出现在作业的输出位置。这是通过在任务提交调用时将提交元数据导出回 Spark 驱动程序来实现的。

## 正在启用 MagicCommitProtocol
<a name="enabling-magic-commit-protocol"></a>

使用 S MagicCommitProtocol 3A 文件系统时，在 Amazon Elastic Map Reduce (EMR) 上运行的 Spark 默认处于启用状态。

要使用 S3A 文件系统，您可以执行以下操作：

1. 定义表、分区或目录时，使用文件方案 `s3a://`。

1. 在 core-site.xml 文件中设置配置 `fs.s3.impl=org.apache.hadoop.fs.s3a.S3AFileSystem`。

## 禁用 MagicCommitProtocol
<a name="disabling-magic-commit-protocol"></a>

1. 您可以将 `spark.sql.execution.datasources.SQLEmrOptimizedCommitProtocol.leverageMagicCommitProtocol` 设置为 false，方法是在 `SparkConf` 中对其进行硬编码，并在 Spark Shell、`spark-submit` 和 `spark-sql` 工具或者 `conf/spark-defaults.conf` 中将其作为 `--conf` 参数进行传递。有关更多信息，请参阅 Apache Spark 文档中的 [Spark 配置](https://spark.apache.org/docs/latest/configuration.html)。

   以下示例说明如何在运行`spark-sql`命令 MagicCommitProtocol 时禁用。

   ```
   spark-sql \
     --conf spark.sql.execution.datasources.SQLEmrOptimizedCommitProtocol.leverageMagicCommitProtocol=false \
   -e "INSERT OVERWRITE TABLE target_table SELECT * FROM source_table;"
   ```

1. 使用 `spark-defaults` 配置分类将 `spark.sql.execution.datasources.SQLEmrOptimizedCommitProtocol.leverageMagicCommitProtocol` 属性设置为 false。有关更多信息，请参阅[配置应用程序](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps.html)。

## MagicCommitProtocol 注意事项
<a name="magic-commit-considerations"></a>
+ 对于静态分区插入，在 Spark 执行器上，任务尝试写入的每个文件都会 MagicCommitProtocol 消耗少量内存，直到任务被提交或中止。在大多数作业中，占用的内存量可以忽略不计。Spark 驱动程序不需要额外的内存
+ 对于动态分区插入，在 Spark 驱动程序上， MagicCommitProtocol 需要内存来存储每个已提交文件的元数据信息，直到作业提交或中止。在大多数任务中，默认的 Spark 驱动程序内存设置可以忽略不计。

  对于包含写入大量文件的长期任务的作业，提交协议占用的内存可能很大，需要调整分配给 Spark 的内存，尤其是 Spark 执行程序。您可以使用 Spark 驱动程序的 `spark.driver.memory` 属性和 `spark.executor.memory` 属性来优化内存。作为指导，编写 100,000 个文件的单个任务通常需要额外的 200MB 内存。有关更多信息，请参阅 Apache Spark 配置文档中的[应用程序属性](https://spark.apache.org/docs/latest/configuration.html#application-properties)。

# 使用经 EMRFS S3 优化的提交程序
<a name="emr-spark-s3-optimized-committer"></a>

EMRFS S3 优化的提交器是一种替代[OutputCommitter](https://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapreduce/OutputCommitter.html)实现，它针对在使用 EMRFS 时将文件写入 Amazon S3 进行了优化。通过避免在任务处理和任务提交阶段列出并重命名在 Amazon S3 中完成的操作来提高应用程序性能。提交程序适用于 Amazon EMR 发行版 5.19.0 及更高版本，在 Amazon EMR 5.20.0 及更高版本中将默认启用。提交者用于使用 Spark DataFrames、或数据集的 Spark 作业。从 Amazon EMR 6.4.0 开始，此提交程序可用于所有常见格式，包括 parquet、ORC 和基于文本的格式（包括 CSV 和 JSON）。对于 Amazon EMR 6.4.0 之前的发行版，仅支持 Parquet 格式。在某些情况下，不使用提交程序。有关更多信息，请参阅 [经 EMRFS S3 优化的提交程序的要求](emr-spark-committer-reqs.md)。

**Topics**
+ [经 EMRFS S3 优化的提交程序的要求](emr-spark-committer-reqs.md)
+ [经 EMRFS S3 优化的提交程序和分段上传](emr-spark-committer-multipart.md)
+ [任务优化注意事项](emr-spark-committer-tuning.md)
+ [为 Amazon EMR 5.19.0 启用经 EMRFS S3 优化的提交程序](emr-spark-committer-enable.md)

# 经 EMRFS S3 优化的提交程序的要求
<a name="emr-spark-committer-reqs"></a>

满足以下条件时，将使用经 EMRFS S3 优化的提交程序：
+ 你运行 Spark 作业，这些任务使用 Spark DataFrames、或数据集将文件写入 Amazon S3。从 Amazon EMR 6.4.0 开始，此提交程序可用于所有常见格式，包括 parquet、ORC 和基于文本的格式（包括 CSV 和 JSON）。对于 Amazon EMR 6.4.0 之前的发行版，仅支持 Parquet 格式。
+ 分段上传在 Amazon EMR 中已启用。这是默认值。有关更多信息，请参阅 [经 EMRFS S3 优化的提交程序和分段上传](emr-spark-committer-multipart.md)。
+ 使用 Spark 的内置文件格式支持。内置文件格式支持用于以下情况：
  + 对于 Hive 元存储表，当 `spark.sql.hive.convertMetastoreParquet` 设置为 `true` 时，可用于 Parquet 表，或 `spark.sql.hive.convertMetastoreOrc` 设置为 `true` 时，可用于 Amazon EMR 6.4.0 或更高版本的 Orc 表。这些是默认设置。
  + 当任务写入文件格式数据来源或表时，例如，使用 `USING parquet` 子句创建目标表。
  + 当作业写入未分区的 Hive 元存储 Parquet 表时。Spark 的内置 Parquet 支持不支持分区的 Hive 表，这是一个已知限制。有关更多信息，请参阅《Apac [he Spark》 DataFrames 和《数据集指南》中的 Hive metastore Parquet 表转换](https://spark.apache.org/docs/latest/sql-data-sources-parquet.html#hive-metastore-parquet-table-conversion)。
+ 写入默认分区位置的 Spark 任务操作，例如 `${table_location}/k1=v1/k2=v2/`，使用提交程序。如果任务操作写入自定义分区位置，则不使用提交程序，例如，如果使用 `ALTER TABLE SQL` 命令设置自定义分区位置。
+ 必须使用 Spark 的以下值：
  + `spark.sql.parquet.fs.optimized.committer.optimization-enabled` 属性必须设置为 `true`。这是 Amazon EMR 5.20.0 及更高版本的默认设置。对于 Amazon EMR 5.19.0，默认值是 `false`。有关配置此值的信息，请参阅[为 Amazon EMR 5.19.0 启用经 EMRFS S3 优化的提交程序](emr-spark-committer-enable.md)。
  + 如果写入非分区的 Hive 元存储表，则仅支持 Parquet 和 Orc 文件格式。如果写入非分区的 Parquet Hive 元存储表，则须将 `spark.sql.hive.convertMetastoreParquet` 设置为 `true`。如果写入非分区的 Orc Hive 元存储表，则 `spark.sql.hive.convertMetastoreOrc` 须设置为 `true`。这些是默认设置。
  + `spark.sql.parquet.output.committer.class` 必须设置为 `com.amazon.emr.committer.EmrOptimizedSparkSqlParquetOutputCommitter`。这是默认设置。
  + 必须将 `spark.sql.sources.commitProtocolClass` 设置为 `org.apache.spark.sql.execution.datasources.SQLEmrOptimizedCommitProtocol` 或 `org.apache.spark.sql.execution.datasources.SQLHadoopMapReduceCommitProtocol`。`org.apache.spark.sql.execution.datasources.SQLEmrOptimizedCommitProtocol` 是 Amazon EMR 5.x 系列 5.30.0 及更高版本以及 Amazon EMR 6.x 系列 6.2.0 及更高版本的默认设置。`org.apache.spark.sql.execution.datasources.SQLHadoopMapReduceCommitProtocol` 是以前 Amazon EMR 版本的默认设置。
  + 如果 Spark 作业用动态分区列覆盖分区的 Parquet 数据集，则 `partitionOverwriteMode` 写入选项和 `spark.sql.sources.partitionOverwriteMode` 必须设置为 `static`。这是默认设置。
**注意**  
Spark 2.4.0 中引入了 `partitionOverwriteMode` 写入选项。对于随附了 Amazon EMR 版本 5.19.0 的 Spark 版本 2.3.2，请设置 `spark.sql.sources.partitionOverwriteMode` 属性。

## 不使用经 EMRFS S3 优化的提交程序的情况
<a name="emr-spark-committer-reqs-anti"></a>

通常，经 EMRFS S3 优化的提交程序不会在以下情况下使用。


****  

| 情况 | 为什么不使用提交程序 | 
| --- | --- | 
| 当您向 HDFS 写入时 | 提交程序只支持使用 EMRFS 写入 Amazon S3。 | 
| 当您使用 S3A 文件系统时 | 提交程序只支持 EMRFS。 | 
| 当你使用 MapReduce 或 Spark 的 RDD API 时 | 提交者仅支持使用 sparkSQL DataFrame、或数据集。 APIs | 

以下 Scala 示例演示了防止经 EMRFS S3 优化的提交程序被整个使用（第一个示例）和部分使用（第二个示例）的一些其他情况。

**Example ：动态分区覆盖模式**  
以下 Scala 示例指示 Spark 使用不同的提交算法，这完全阻止了经 EMRFS S3 优化的提交程序的使用。该代码将 `partitionOverwriteMode` 属性设置为 `dynamic`，以仅覆盖您的数据所写入到的分区。然后，通过 `partitionBy` 指定动态分区列，并将写入模式设置为 `overwrite`。  

```
val dataset = spark.range(0, 10)
  .withColumn("dt", expr("date_sub(current_date(), id)"))

dataset.write.mode("overwrite")
  .option("partitionOverwriteMode", "dynamic")
  .partitionBy("dt")
  .parquet("s3://amzn-s3-demo-bucket1/output")
```
您必须配置所有三项设置，以避免使用经 EMRFS S3 优化的提交程序。当您执行此操作时，Spark 会执行在 Spark 的提交协议中指定的不同提交算法。对于早于 5.30.0 的 Amazon EMR 5.x 发行版和早于 6.2.0 的 Amazon EMR 6.x 发行版，提交协议使用 Spark 的暂存目录，该目录是在以 `.spark-staging` 开头的输出位置下创建的临时目录。该算法按顺序对分区目录进行重命名，这可能会对性能产生负面影响。有关 Amazon EMR 发行版 5.30.0 及更高版本和 6.2.0 及更高版本的更多信息，请参阅 [使用经 EMRFS S3 优化的提交协议](emr-spark-s3-optimized-commit-protocol.md)。  
Spark 2.4.0 中的算法遵循以下步骤：  

1. 任务尝试将其输出写入 Spark 的暂存目录下的分区目录，例如 `${outputLocation}/spark-staging-${jobID}/k1=v1/k2=v2/`。

1. 对于写入的每个分区，任务尝试都跟踪相对分区路径，例如 `k1=v1/k2=v2`。

1. 任务成功完成后，它会为驱动程序提供它跟踪的所有相对分区路径。

1. 完成所有任务后，作业提交阶段将收集成功任务尝试在 Spark 的暂存目录下写入的所有分区目录。Spark 使用目录树重命名操作按顺序将这些目录的每一个都重命名为其最终输出位置。

1. 暂存目录会在作业提交阶段完成之前删除。

**Example ：自定义分区位置**  
在此示例中，Scala 代码插入到两个分区中。一个分区具有自定义分区位置。另一个分区使用默认分区位置。经 EMRFS S3 优化的提交程序仅用于将任务输出写入到使用默认分区位置的分区。  

```
val table = "dataset"
val location = "s3://bucket/table"
                            
spark.sql(s"""
  CREATE TABLE $table (id bigint, dt date) 
  USING PARQUET PARTITIONED BY (dt) 
  LOCATION '$location'
""")
                            
// Add a partition using a custom location
val customPartitionLocation = "s3://bucket/custom"
spark.sql(s"""
  ALTER TABLE $table ADD PARTITION (dt='2019-01-28') 
  LOCATION '$customPartitionLocation'
""")
                            
// Add another partition using default location
spark.sql(s"ALTER TABLE $table ADD PARTITION (dt='2019-01-29')")
                            
def asDate(text: String) = lit(text).cast("date")
                            
spark.range(0, 10)
  .withColumn("dt",
    when($"id" > 4, asDate("2019-01-28")).otherwise(asDate("2019-01-29")))
  .write.insertInto(table)
```
Scala 代码创建以下 Amazon S3 对象：  

```
custom/part-00001-035a2a9c-4a09-4917-8819-e77134342402.c000.snappy.parquet
custom_$folder$
table/_SUCCESS
table/dt=2019-01-29/part-00000-035a2a9c-4a09-4917-8819-e77134342402.c000.snappy.parquet
table/dt=2019-01-29_$folder$
table_$folder$
```
当写入到自定义位置的分区时，Spark 会使用类似于上一个示例的提交算法，如下所述。与前面的示例一样，该算法会导致顺序重命名，这可能会影响性能。  

1. 在将输出写入自定义位置的分区时，任务会写入到 Spark 的暂存目录下的文件中，该目录是在最终输出位置下创建的。该文件的名称包含一个随机 UUID，以防止文件冲突。任务尝试跟踪每个文件以及最终所需的输出路径。

1. 在任务成功完成后，它会为驱动程序提供这些文件及其最终所需的输出路径。

1. 所有任务都完成后，作业提交阶段会按顺序将为自定义位置的分区写入的所有文件重命名为其最终输出路径。

1. 暂存目录会在作业提交阶段完成之前删除。

# 经 EMRFS S3 优化的提交程序和分段上传
<a name="emr-spark-committer-multipart"></a>

要使用经 EMRFS S3 优化的提交程序，则必须为 Amazon EMR 启用分段上传。默认启用分段上传。需要时，您可以重新启用它。有关更多信息，请参阅《Amazon EMR 管理指南》**中的[为 Amazon S3 配置分段上传](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-upload-s3.html#Config_Multipart)。

经 EMRFS S3 优化的提交程序利用分段上传类似于事务的特征，来确保由任务写入的文件在任务提交后尝试仅显示在作业的输出位置。通过以这种方式使用分段上传，提交者比默认 FileOutputCommitter 算法版本 2 提高了任务提交性能。使用经 EMRFS S3 优化的提交程序时，有一些与传统分段上传行为的关键区别需要考虑：
+ 无论文件大小如何，分段上传都会执行。这不同于 EMRFS 的默认行为，其中 `fs.s3n.multipart.uploads.split.size` 属性在触发分段上传时，控制文件大小。
+ 在任务提交或中止之前，分段上传在较长时间内都保持在未完成状态。这不同于 EMRFS 的默认行为，其中分段上传在任务完成写入给定文件时完成。

由于这些区别，如果 Spark Executor JVM 在任务正在运行或将数据写入到 Amazon S3 时发生崩溃或被终止，未完成的分段上传更可能被留下来。因此，当您使用经 EMRFS S3 优化的提交程序时，请务必遵循管理失败的分段上传的最佳实践。有关更多信息，请参阅《Amazon EMR 管理指南》**中使用 Amazon S3 存储桶的[最佳实践](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-upload-s3.html#emr-bucket-bestpractices)。

# 任务优化注意事项
<a name="emr-spark-committer-tuning"></a>

在任务被提交或中止之前，经 EMRFS S3 优化的提交程序会占用少量内存来存放任务尝试写入的每个文件。在大多数作业中，占用的内存量可以忽略不计。对于包含写入大量文件的长期任务的作业，提交程序占用的内存可能很大，需要调整为 Spark 执行程序分配的内存。您可以使用 `spark.executor.memory` 属性调整执行程序内存。作为指导，编写 100000 个文件的单个任务通常需要额外的 100 MB 内存。有关更多信息，请参阅 Apache Spark 配置文档中的[应用程序属性](https://spark.apache.org/docs/latest/configuration.html#application-properties)。

# 为 Amazon EMR 5.19.0 启用经 EMRFS S3 优化的提交程序
<a name="emr-spark-committer-enable"></a>

如果您使用的是 Amazon EMR 5.19.0，则可以在从 Spark 中创建集群时手动将 `spark.sql.parquet.fs.optimized.committer.optimization-enabled` 属性设置为 `true`（如果您使用的是 Amazon EMR）。

## 在创建集群时启用经 EMRFS S3 优化的提交程序
<a name="w2aac62c61c17c13b5"></a>

使用 `spark-defaults` 配置分类将 `spark.sql.parquet.fs.optimized.committer.optimization-enabled` 属性设置为 `true`。有关更多信息，请参阅[配置应用程序](emr-configure-apps.md)。

## 从 Spark 启用经 EMRFS S3 优化的提交程序
<a name="w2aac62c61c17c13b7"></a>

您可以将 `spark.sql.parquet.fs.optimized.committer.optimization-enabled` 设置为 `true`，方法是在 `SparkConf` 中对其进行硬编码，并在 Spark Shell 或 `spark-submit` 和 `spark-sql` 工具或 `conf/spark-defaults.conf` 中将其作为 `--conf` 参数进行传递。有关更多信息，请参阅 Apache Spark 文档中的 [Spark 配置](https://spark.apache.org/docs/latest/configuration.html)。

以下示例显示了如何在运行 spark-sql 命令的同时启用提交程序。

```
spark-sql \
  --conf spark.sql.parquet.fs.optimized.committer.optimization-enabled=true \
  -e "INSERT OVERWRITE TABLE target_table SELECT * FROM source_table;"
```

# 使用经 EMRFS S3 优化的提交协议
<a name="emr-spark-s3-optimized-commit-protocol"></a>

EMRFS S3 优化的提交协议是一种替代[FileCommitProtocol](https://spark.apache.org/docs/2.2.0//api/java/org/apache/spark/internal/io/FileCommitProtocol.html)实现，它经过优化，可在使用 EMRFS 时将带有 Spark 动态分区覆盖的文件写入 Amazon S3。该协议可在 Spark 动态分区覆盖任务提交阶段避免 Amazon S3 中的重命名操作，从而提高应用程序性能。

请注意，[经 EMRFS S3 优化的提交程序](emr-spark-s3-optimized-committer.html)也可以通过避免重命名操作来提高性能。但是，它不适用于动态分区覆盖情况，同时提交协议的改进仅针对动态分区覆盖情况。

提交协议适用于 Amazon EMR 发行版 5.30.0 及更高版本，在 Amazon EMR 6.2.0 及更高版本中将默认启用。从发行版 5.31.0 开始，Amazon EMR 增加了并行性改进。该协议用于使用 Spark DataFrames、或数据集的 Spark 作业。在某些情况下，不使用提交协议。有关更多信息，请参阅 [经 EMRFS S3 优化的提交协议的要求](emr-spark-committer-reqs.md)。

**Topics**
+ [经 EMRFS S3 优化的提交协议的要求](emr-spark-commit-protocol-reqs.md)
+ [经 EMRFS S3 优化的提交协议和分段上传](emr-spark-commit-protocol-multipart.md)
+ [任务优化注意事项](emr-spark-commit-protocol-tuning.md)

# 经 EMRFS S3 优化的提交协议的要求
<a name="emr-spark-commit-protocol-reqs"></a>

满足以下条件时，将使用经 EMRFS S3 优化的提交协议：
+ 你运行使用 Spark DataFrames、或数据集来覆盖分区表的 Spark 作业。
+ 您可以运行分区覆盖模式为 `dynamic` 的 Spark 任务。
+ 分段上传在 Amazon EMR 中已启用。这是默认值。有关更多信息，请参阅 [经 EMRFS S3 优化的提交协议和分段上传](emr-spark-commit-protocol-multipart.md)。
+ EMRFS 的文件系统缓存已启用。这是默认值。检查设置 `fs.s3.impl.disable.cache` 是否设置为 `false`。
+ 使用 Spark 的内置数据来源支持。内置数据来源支持用于以下情况：
  + 当任务写入内置数据来源或表时。
  + 当任务写入 Hive 元存储 Parquet 表时。当 `spark.sql.hive.convertInsertingPartitionedTable` 和 `spark.sql.hive.convertMetastoreParquet` 都设置为 true 时，就会发生这种情况。这些是默认设置。
  + 当任务写入 Hive 元存储 ORC 表时。当 `spark.sql.hive.convertInsertingPartitionedTable` 和 `spark.sql.hive.convertMetastoreOrc` 都设置为 `true` 时，就会发生这种情况。这些是默认设置。
+ 写入默认分区位置的 Spark 任务操作，例如 `${table_location}/k1=v1/k2=v2/`，使用提交协议。如果任务操作写入自定义分区位置，则不使用协议，例如，如果使用 `ALTER TABLE SQL` 命令设置自定义分区位置。
+ 必须使用 Spark 的以下值：
  + `spark.sql.sources.commitProtocolClass` 必须设置为 `org.apache.spark.sql.execution.datasources.SQLEmrOptimizedCommitProtocol`。这是 Amazon EMR 发行版 5.30.0 及更高版本和 Amazon EMR 发行版 6.2.0 及更高版本的默认设置。
  + `partitionOverwriteMode` 写入选项或 `spark.sql.sources.partitionOverwriteMode` 必须设置为 `dynamic`。默认设置为 `static`。
**注意**  
Spark 2.4.0 中引入了 `partitionOverwriteMode` 写入选项。对于随附了 Amazon EMR 版本 5.19.0 的 Spark 版本 2.3.2，请设置 `spark.sql.sources.partitionOverwriteMode` 属性。
  + 如果 Spark 任务覆盖了 Hive 元存储 Parquet 表，则 `spark.sql.hive.convertMetastoreParquet`、`spark.sql.hive.convertInsertingPartitionedTable` 和 `spark.sql.hive.convertMetastore.partitionOverwriteMode` 必须设置为 `true`。这些是默认设置。
  + 如果 Spark 任务覆盖了 Hive 元存储 ORC 表，则 `spark.sql.hive.convertMetastoreOrc`、`spark.sql.hive.convertInsertingPartitionedTable` 和 `spark.sql.hive.convertMetastore.partitionOverwriteMode` 必须设置为 `true`。这些是默认设置。

**Example ：动态分区覆盖模式**  
在此 Scala 示例中已触发优化。首先，将 `partitionOverwriteMode` 属性设置为 `dynamic`。这只会覆盖您正在写入数据的那些分区。然后，通过 `partitionBy` 指定动态分区列，并将写入模式设置为 `overwrite`。  

```
val dataset = spark.range(0, 10)
  .withColumn("dt", expr("date_sub(current_date(), id)"))

dataset.write.mode("overwrite")                 // "overwrite" instead of "insert"
  .option("partitionOverwriteMode", "dynamic")  // "dynamic" instead of "static"  
  .partitionBy("dt")                            // partitioned data instead of unpartitioned data
  .parquet("s3://amzn-s3-demo-bucket1/output")    // "s3://" to use Amazon EMR file system, instead of "s3a://" or "hdfs://"
```

## 当不使用经 EMRFS S3 优化的提交协议时
<a name="emr-spark-commit-protocol-reqs-anti"></a>

通常，经 EMRFS S3 优化的提交协议的工作原理与开源默认 Spark 提交协议 `org.apache.spark.sql.execution.datasources.SQLHadoopMapReduceCommitProtocol` 相同。以下情况下不会进行优化。


****  

| 情况 | 为什么不使用提交协议 | 
| --- | --- | 
| 当您向 HDFS 写入时 | 提交协议只支持使用 EMRFS 写入 Amazon S3。 | 
| 当您使用 S3A 文件系统时 | 提交协议只支持 EMRFS。 | 
| 当你使用 MapReduce 或 Spark 的 RDD API 时 | 提交协议仅支持使用 sparkSQL DataFrame、或数据集。 APIs | 
| 当没有触发动态分区覆盖时 | 提交协议仅优化动态分区覆盖情况。有关其他情况，请参阅 [使用经 EMRFS S3 优化的提交程序](emr-spark-s3-optimized-committer.md)。 | 

以下 Scala 示例演示了经 EMRFS S3 优化的提交协议委托给 `SQLHadoopMapReduceCommitProtocol` 的一些其他情况。

**Example ：具有自定义分区位置的动态分区覆盖模式**  
在此示例中，Scala 程序以动态分区覆盖模式覆盖两个分区。一个分区具有自定义分区位置。另一个分区使用默认分区位置。经 EMRFS S3 优化的提交协议仅改进了使用默认分区位置的分区。  

```
val table = "dataset"
val inputView = "tempView"
val location = "s3://bucket/table"
                            
spark.sql(s"""
  CREATE TABLE $table (id bigint, dt date) 
  USING PARQUET PARTITIONED BY (dt) 
  LOCATION '$location'
""")

// Add a partition using a custom location
val customPartitionLocation = "s3://bucket/custom"
spark.sql(s"""
  ALTER TABLE $table ADD PARTITION (dt='2019-01-28') 
  LOCATION '$customPartitionLocation'
""")

// Add another partition using default location
spark.sql(s"ALTER TABLE $table ADD PARTITION (dt='2019-01-29')")

def asDate(text: String) = lit(text).cast("date")   
                       
spark.range(0, 10)
  .withColumn("dt",
    when($"id" > 4, asDate("2019-01-28")).otherwise(asDate("2019-01-29")))
  .createTempView(inputView)
  
// Set partition overwrite mode to 'dynamic'
spark.sql(s"SET spark.sql.sources.partitionOverwriteMode=dynamic")
  
spark.sql(s"INSERT OVERWRITE TABLE $table SELECT * FROM $inputView")
```
Scala 代码创建以下 Amazon S3 对象：  

```
custom/part-00001-035a2a9c-4a09-4917-8819-e77134342402.c000.snappy.parquet
custom_$folder$
table/_SUCCESS
table/dt=2019-01-29/part-00000-035a2a9c-4a09-4917-8819-e77134342402.c000.snappy.parquet
table/dt=2019-01-29_$folder$
table_$folder$
```
在早期 Spark 版本中写入自定义分区位置可能会导致数据丢失。在此示例中，分区 `dt='2019-01-28'` 将丢失。有关详细信息，请参阅 [SPARK-35106](https://issues.apache.org/jira/browse/SPARK-35106)。此问题已在 Amazon EMR 发行版 5.33.0 及更高版本（6.0.x 和 6.1.x 除外）中得到修复。

当写入到自定义位置的分区时，Spark 会使用类似于上一个示例的提交算法，如下所述。与前面的示例一样，该算法会导致顺序重命名，这可能会影响性能。

Spark 2.4.0 中的算法遵循以下步骤：

1. 在将输出写入自定义位置的分区时，任务会写入到 Spark 的暂存目录下的文件中，该目录是在最终输出位置下创建的。该文件的名称包含一个随机 UUID，以防止文件冲突。任务尝试跟踪每个文件以及最终所需的输出路径。

1. 在任务成功完成后，它会为驱动程序提供这些文件及其最终所需的输出路径。

1. 所有任务都完成后，作业提交阶段会按顺序将为自定义位置的分区写入的所有文件重命名为其最终输出路径。

1. 暂存目录会在作业提交阶段完成之前删除。

# 经 EMRFS S3 优化的提交协议和分段上传
<a name="emr-spark-commit-protocol-multipart"></a>

要在经 EMRFS S3 优化的提交协议中使用动态分区覆盖优化，必须在 Amazon EMR 中启用分段上传。默认启用分段上传。需要时，您可以重新启用它。有关更多信息，请参阅《Amazon EMR 管理指南》**中的[为 Amazon S3 配置分段上传](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-upload-s3.html#Config_Multipart)。

在动态分区覆盖期间，经 EMRFS S3 优化的提交协议利用分段上传类似于事务的特征，来确保由任务写入的文件在任务提交后尝试仅显示在任务的输出位置。通过以这种方式使用分段上传，提交协议提高了默认 `SQLHadoopMapReduceCommitProtocol` 的任务提交性能。使用经 EMRFS S3 优化的提交协议时，需要考虑一些与传统分段上传行为的关键区别：
+ 无论文件大小如何，分段上传都会执行。这不同于 EMRFS 的默认行为，其中 `fs.s3n.multipart.uploads.split.size` 属性在触发分段上传时，控制文件大小。
+ 在任务提交或中止之前，分段上传在较长时间内都保持在未完成状态。这不同于 EMRFS 的默认行为，其中分段上传在任务完成写入给定文件时完成。

由于这些区别，如果 Spark Executor JVM 在任务正在运行或将数据写入 Amazon S3 时发生崩溃或被终止，或者 Spark Driver JVM 在任务正在运行时发生崩溃或被终止，未完成的分段上传更可能会被留下来。因此，当您使用经 EMRFS S3 优化的提交协议时，请务必遵循管理失败的分段上传的最佳实践。有关更多信息，请参阅《Amazon EMR 管理指南》**中使用 Amazon S3 存储桶的[最佳实践](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-upload-s3.html#emr-bucket-bestpractices)。

# 任务优化注意事项
<a name="emr-spark-commit-protocol-tuning"></a>

在 Spark 执行程序上，经 EMRFS S3 优化的提交协议会占用少量内存来存储任务尝试写入的每个文件，直到任务提交或中止。在大多数作业中，占用的内存量可以忽略不计。

在 Spark 驱动程序上，经 EMRFS S3 优化的提交协议需要内存来存储每个已提交文件的元数据信息，直到任务提交或中止。在大多数任务中，默认的 Spark 驱动程序内存设置可以忽略不计。

对于包含写入大量文件的长期任务的作业，提交协议占用的内存可能很大，需要调整分配给 Spark 的内存，尤其是 Spark 执行程序。您可以使用 Spark 驱动程序的 `spark.driver.memory` 属性和 `spark.executor.memory` 属性来优化内存。作为指导，编写 100000 个文件的单个任务通常需要额外的 100 MB 内存。有关更多信息，请参阅 Apache Spark 配置文档中的[应用程序属性](https://spark.apache.org/docs/latest/configuration.html#application-properties)。

# 使用 EMRFS 重试 Amazon S3 请求
<a name="emr-spark-emrfs-retry"></a>

本主题提供有关使用 EMRFS 向 Amazon S3 发出请求时可以使用的重试策略的信息。当您的请求速率提高时，S3 会尝试扩展以支持新的速率。在此过程中，S3 可以限制请求并返回 `503 Slow Down` 错误。为了提高 S3 请求的成功率，您可以通过在 `emrfs-site` 配置中配置属性以调整重试策略。

您可以通过以下方法调整重试策略。
+ 提高默认指数退避重试策略的最大重试限制。
+ 启用和配置加性增长/加速递减 (AIMD) 重试策略。Amazon EMR 发行版 6.4.0 及更高版本支持 AIMD。

## 使用默认的指数退避策略
<a name="emr-spark-emrfs-retry-exponential-backoff"></a>

默认情况下，EMRFS 使用指数退避策略来重试 Amazon S3 请求。默认 EMRFS 重试限制为 15。为避免 S3 `503 Slow Down` 错误，您可以在创建新集群时、在正在运行的群集上或应用程序运行时提高重试限制。

要提高重试限制，您必须在您的 `emrfs-site` 配置中更改 `fs.s3.maxRetries` 的值。以下示例配置将 `fs.s3.maxRetries` 设置为自定义值 30。

```
[
    {
      "Classification": "emrfs-site",
      "Properties": {
        "fs.s3.maxRetries": "30"
      }
    }
]
```

有关使用配置对象的更多信息，请参阅 [配置应用程序](emr-configure-apps.md)。

## 使用 AIMD 重试策略
<a name="emr-spark-emrfs-retry-aimd"></a>

在 Amazon EMR 发行版 6.4.0 及更高版本中，EMRFS 支持基于加性增长/加速递减（AIMD）模型的替代重试策略。当您使用大型 Amazon EMR 集群时，AIMD 重试策略尤其有用。

AIMD 使用有关最近成功请求的数据计算自定义请求率。此策略减少了受限请求的数量和每个请求所需的总尝试次数。

要启用 AIMD 重试策略，必须在您的 `emrfs-site` 配置中将 `fs.s3.aimd.enabled` 属性设置为 `true`，如以下示例所示。

```
[
    {
      "Classification": "emrfs-site",
      "Properties": {
        "fs.s3.aimd.enabled": "true"
      }
    }
]
```

有关使用配置对象的更多信息，请参阅 [配置应用程序](emr-configure-apps.md)。

## 高级 AIMD 重试设置
<a name="emr-spark-emrfs-retry-advanced-properties"></a>

您可以配置下表中列出的属性，以便在使用 AIMD 重试策略时优化重试行为。对于大多数使用案例，我们建议您使用默认值。


**高级 AIMD 重试策略属性**  

| 属性 | 默认 值 | 说明 | 
| --- | --- | --- | 
| fs.s3.aimd.increaseIncrement | 0.1 | 控制连续请求成功时请求速率的增长速度。 | 
| fs.s3.aimd.reductionFactor | 2 | 控制 Amazon S3 返回 503 响应时请求速率降低的速度。默认因子 2 将请求率降低一半。 | 
| fs.s3.aimd.minRate | 0.1 | 设置请求经历 S3 持续限制时的请求速率的下限。 | 
| fs.s3.aimd.initialRate | 5500 | 设置初始请求速率，然后该速率将根据您为 fs.s3.aimd.increaseIncrement 和 fs.s3.aimd.reductionFactor 指定的值变化。初始速率也用于 GET 请求，并针对 PUT 请求按比例 (3500/5500) 扩展。 | 
| fs.s3.aimd.adjustWindow | 2 | 控制调整请求速率的频率，以响应数量衡量。 | 
| fs.s3.aimd.maxAttempts | 100 | 设置尝试请求的最大尝试次数。 | 

# 添加 Spark 步骤
<a name="emr-spark-submit-step"></a>

您可以使用 Amazon EMR 步骤向安装在 EMR 集群上的 Spark 框架提交工作。有关更多信息，请参阅《Amazon EMR 管理指南》中的[步骤](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-overview.html#emr-overview-data-processing)。在控制台和 CLI 中，您使用 Spark 应用程序步骤 (代表您将 `spark-submit` 脚本作为步骤运行) 来完成此操作。借助 API，您通过 `spark-submit` 使用步骤调用 `command-runner.jar`。

有关向 Spark 提交应用程序的更多信息，请参阅 Apache Spark 文档中的[提交应用程序](https://spark.apache.org/docs/latest/submitting-applications.html)主题。

**使用控制台提交 Spark 步骤**

1. [在 /emr 上打开亚马逊 EMR 控制台。https://console.aws.amazon.com](https://console.aws.amazon.com/emr/)

1. 在 **Cluster List (集群列表)** 中，选择您的集群的名称。

1. 滚动到 **Steps (步骤)** 部分并展开它，然后选择 **Add step (添加步骤)**。

1. 在 **Add Step (添加步骤)** 对话框中：
   + 对于 **Step type (步骤类型)**，选择 **Spark application (Spark 应用程序)**。
   + 对于 **Name**（名称），接受原定设置名称（Spark application）或键入一个新名称。
   + 对于 **Deploy mode (部署模式)**，选择 **Client (客户端)** 或 **Cluster (集群)** 模式。客户端模式在集群的主实例上启动驱动程序，而集群模式在集群上启动驱动程序。对于客户端模式，驱动程序的日志输出将显示在步骤日志中，而对于集群模式，驱动程序的日志输出将显示在第一个 YARN 容器的日志中。有关更多信息，请参阅 Apache Spark 文档中的[集群模式概览](https://spark.apache.org/docs/latest/cluster-overview.html)。
   + 指定所需的 **Spark-submit options**。有关 `spark-submit` 选项的更多信息，请参阅[使用 spark-submit 启动应用程序](https://spark.apache.org/docs/latest/submitting-applications.html#launching-applications-with-spark-submit)。
   + 对于 **Application location (应用程序位置)**，指定应用程序的本地或 S3 URI 路径。
   + 对于 **Arguments (参数)**，将该字段保留为空白。
   + 对于 **Action on failure (出现故障时的操作)**，接受默认选项 **Continue (继续)**。

1. 选择**添加**。步骤会出现在控制台中，其状态为“Pending”。

1. 步骤的状态会随着步骤的运行从**“Pending”**变为**“Running”**，再变为**“Completed”**。要更新状态，请选择 **Actions (操作)** 列上方的 **Refresh (刷新)** 图标。

1. 如果您配置了日志记录，则这一步的结果将放在 Amazon EMR 控制台的 Cluster Details (集群详细信息) 页面上，位于您的步骤旁边的 **Log Files (日志文件)** 下方。在启动集群时，您可以选择在配置的日志存储桶中查找步骤信息。

**要使用 Spark 将作品提交给 Spark AWS CLI**

在创建集群时提交步骤，或使用 `aws emr add-steps` 子命令在现有集群中提交步骤。

1. 使用 `create-cluster`，如以下示例所示。
**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

   ```
   aws emr create-cluster --name "Add Spark Step Cluster" --release-label emr-7.12.0 --applications Name=Spark \
   --ec2-attributes KeyName=myKey --instance-type m5.xlarge --instance-count 3 \
   --steps Type=Spark,Name="Spark Program",ActionOnFailure=CONTINUE,Args=[--class,org.apache.spark.examples.SparkPi,/usr/lib/spark/examples/jars/spark-examples.jar,10] --use-default-roles
   ```

   作为替代方法，您可使用 `command-runner.jar`，如以下示例所示。

   ```
   aws emr create-cluster --name "Add Spark Step Cluster" --release-label emr-7.12.0 \
   --applications Name=Spark --ec2-attributes KeyName=myKey --instance-type m5.xlarge --instance-count 3 \
   --steps Type=CUSTOM_JAR,Name="Spark Program",Jar="command-runner.jar",ActionOnFailure=CONTINUE,Args=[spark-example,SparkPi,10] --use-default-roles
   ```
**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

1. 或者，向正在运行的集群添加步骤。使用 `add-steps`。

   ```
   aws emr add-steps --cluster-id j-2AXXXXXXGAPLF --steps Type=Spark,Name="Spark Program",ActionOnFailure=CONTINUE,Args=[--class,org.apache.spark.examples.SparkPi,/usr/lib/spark/examples/jars/spark-examples.jar,10]
   ```

   作为替代方法，您可使用 `command-runner.jar`，如以下示例所示。

   ```
   aws emr add-steps --cluster-id j-2AXXXXXXGAPLF --steps Type=CUSTOM_JAR,Name="Spark Program",Jar="command-runner.jar",ActionOnFailure=CONTINUE,Args=[spark-example,SparkPi,10]
   ```

**使用 SDK for Java 向 Spark 提交工作**

1. 下面的示例显示如何通过 Java 添加步骤至带有 Spark 的集群：

   ```
   AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
   AmazonElasticMapReduce emr = new AmazonElasticMapReduceClient(credentials);
    
   StepFactory stepFactory = new StepFactory();
   AmazonElasticMapReduceClient emr = new AmazonElasticMapReduceClient(credentials);
   AddJobFlowStepsRequest req = new AddJobFlowStepsRequest();
   req.withJobFlowId("j-1K48XXXXXXHCB");
   
   List<StepConfig> stepConfigs = new ArrayList<StepConfig>();
   		
   HadoopJarStepConfig sparkStepConf = new HadoopJarStepConfig()
   			.withJar("command-runner.jar")
   			.withArgs("spark-submit","--executor-memory","1g","--class","org.apache.spark.examples.SparkPi","/usr/lib/spark/examples/jars/spark-examples.jar","10");			
   		
   StepConfig sparkStep = new StepConfig()
   			.withName("Spark Step")
   			.withActionOnFailure("CONTINUE")
   			.withHadoopJarStep(sparkStepConf);
   
   stepConfigs.add(sparkStep);
   req.withSteps(stepConfigs);
   AddJobFlowStepsResult result = emr.addJobFlowSteps(req);
   ```

1. 您可以通过查看该步骤的日志来了解该步骤的结果。 AWS 管理控制台 如果您启用了日志记录，则可以在中执行此操作，方法是选择 “**步骤**”，选择您的步骤，然后在 “**日志文件**” 中，选择`stdout`或`stderr`。要查看可用日志，请选择 **View Logs (查看日志)**。

## 覆盖 Spark 默认配置设置
<a name="dynamic-configuration"></a>

建议您为不同的应用程序覆盖 Spark 默认配置值。您可以在提交应用程序时使用步骤完成此操作 (实质上是向 `spark-submit` 传递选项)。例如，您可能需要通过更改 `spark.executor.memory` 来更改为执行者进程分配的内存。您可以为 `--executor-memory` 开关提供类似下面的参数：

```
spark-submit --executor-memory 1g --class org.apache.spark.examples.SparkPi /usr/lib/spark/examples/jars/spark-examples.jar 10
```

同样地，您也可以调节 `--executor-cores` 和 `--driver-memory`。在步骤中，您可以向步骤提供以下参数：

```
--executor-memory 1g --class org.apache.spark.examples.SparkPi /usr/lib/spark/examples/jars/spark-examples.jar 10
```

您还可以使用 `--conf` 选项调节没有内置开关的设置。有关可调节的其他设置的更多信息，请参阅 Apache Spark 文档中的[动态加载 Spark 属性](https://spark.apache.org/docs/latest/configuration.html#dynamically-loading-spark-properties)主题。

# 查看 Spark 应用程序历史记录
<a name="emr-spark-application-history"></a>

您可以在控制台中，使用集群详细信息页面上的 **Application user interfaces (应用程序用户界面)** 选项卡查看 Spark、YARN 应用程序和 Tez UI 详细信息。通过使用 Amazon EMR 应用程序用户界面（UI），您可以更轻松地对活动的作业和任务历史记录进行故障排查和分析。

有关更多信息，请参阅《Amazon EMR 管理指南》**中的[查看应用程序历史记录](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-cluster-application-history.html)。

# 访问 Spark 网站 UIs
<a name="emr-spark-webui"></a>

您可以 UIs 按照《Amazon EMR 管理指南》中名为 “[连接到集群” 的部分创建 SSH 隧道或创建代理的过程查看 Spark 网页，然后导航到集群](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node.html)的 YARN ResourceManager 。在 **Tracking UI (跟踪 UI)** 下选择适合您的应用程序的链接。如果您的应用程序正在运行，则会看到**ApplicationMaster**。这会将您带到主应用程序的 Web UI，在端口 20888 上，无论驱动程序位于何处都是如此。如果您在 YARN 客户端模式下运行，则驱动程序可能会位于集群的主节点上。如果您在 YARN 集群模式下运行应用程序，则驱动程序位于集群上应用程序 ApplicationMaster 的驱动程序中。如果您的应用程序已完成，您将看到**历史记录**，它会将您带到位于 EMR 集群主节点 18080 的 Spark HistoryServer UI 端口号。这适用于已经完成的应用程序。你也可以直接通过 http: //: 18080/ *master-public-dns-name* 导航到 Spark HistoryServer 用户界面。

在 Amazon EMR 发行版 5.25.0 或更高版本中，可以从控制台访问 Spark 历史记录服务器 UI，而无需通过 SSH 连接设置 Web 代理。有关更多信息，请参阅[查看持久性应用程序用户界面](https://docs.aws.amazon.com/emr/latest/ManagementGuide/app-history-spark-UI.html)。

# 使用 Spark 结构化流 Amazon Kinesis Data Streams 连接器
<a name="emr-spark-structured-streaming-kinesis"></a>

Amazon EMR 7.1.0 及更高版本在发布映像中包含 Spark 结构化流 Amazon Kinesis Data Streams 连接器。通过此连接器，您可以使用 Amazon EMR 上的 Spark 来处理存储在 Amazon Kinesis Data Streams 中的数据。该连接器支持两种使用者类型 `GetRecords`（共享吞吐量）和 `SubscribeToShard`（增强扇出）。此集成基于 [https://github.com/awslabs/spark-sql-kinesis-connector](https://github.com/awslabs/spark-sql-kinesis-connector)。有关如何开始使用连接器的详细信息，请参阅 [README](https://github.com/awslabs/spark-sql-kinesis-connector/blob/main/README.md)。

以下示例演示了如何使用连接器通过 Amazon EMR 启动 Spark 应用程序

```
spark-submit my_kinesis_streaming_script.py
```

# 将适用于 Apache Spark 的 Amazon Redshift 集成与 Amazon EMR 结合使用
<a name="emr-spark-redshift"></a>

在 Amazon EMR 发行版 6.4.0 及更高版本中，每个版本的映像都包含 [Apache Spark](https://aws.amazon.com/emr/features/spark/) 和 Amazon Redshift 之间的连接器。通过该连接器，您可以在 Amazon EMR 上使用 Spark 处理存储在 Amazon Redshift 中的数据。对于 Amazon EMR 发行版 6.4.0 至 6.8.0，集成基于 [`spark-redshift` 开源连接器](https://github.com/spark-redshift-community/spark-redshift#readme)。对于 Amazon EMR 发行版 6.9.0 及更高版本，[适用于 Apache Spark 的 Amazon Redshift 集成](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)已从社区版本迁移到本地集成。

**Topics**
+ [使用适用于 Apache Spark 的 Amazon Redshift 集成启动 Spark 应用程序](emr-spark-redshift-launch.md)
+ [使用适用于 Apache Spark 的 Amazon Redshift 集成进行身份验证](emr-spark-redshift-auth.md)
+ [在 Amazon Redshift 中进行读取和写入](emr-spark-redshift-readwrite.md)
+ [使用 Spark 连接器时的注意事项和限制](emr-spark-redshift-considerations.md)

# 使用适用于 Apache Spark 的 Amazon Redshift 集成启动 Spark 应用程序
<a name="emr-spark-redshift-launch"></a>

对于 Amazon EMR 版本 6.4 至 6.9，您必须使用 `--jars` 或 `--packages` 选项来指定要使用以下哪个 JAR 文件。`--jars` 选项指定存储在本地、HDFS 中或使用 HTTP/S 的依赖项。要查看 `--jars` 选项支持的其他文件位置，请参阅 Spark 文档中的[高级依赖管理](https://spark.apache.org/docs/latest/submitting-applications.html#advanced-dependency-management)。`--packages` 选项指定存储在公共 Maven 存储库中的依赖项。
+ `spark-redshift.jar`
+ `spark-avro.jar`
+ `RedshiftJDBC.jar`
+ `minimal-json.jar`

Amazon EMR 6.10.0 及更高版本不需要 `minimal-json.jar` 依赖关系，并且默认情况下会自动将其他依赖项安装到每个集群。以下示例显示了如何使用适用于 Apache Spark 的 Amazon Redshift 集成启动 Spark 应用程序。

------
#### [ Amazon EMR 6.10.0 \$1 ]

以下示例显示了如何在 Amazon EMR 版本 6.10 和更高版本上使用 `spark-redshift` 连接器启动 Spark 应用程序。

```
spark-submit my_script.py
```

------
#### [ Amazon EMR 6.4.0 - 6.9.x ]

要在 Amazon EMR 版本 6.4 至 6.9 上通过 `spark-redshift` 连接器启动 Spark 应用程序，必须使用 `--jars` 或 `--packages` 选项，如以下例所示。请注意，`--jars` 选项列出的路径是 JAR 文件的默认路径。

```
spark-submit \
  --jars /usr/share/aws/redshift/jdbc/RedshiftJDBC.jar,/usr/share/aws/redshift/spark-redshift/lib/spark-redshift.jar,/usr/share/aws/redshift/spark-redshift/lib/spark-avro.jar,/usr/share/aws/redshift/spark-redshift/lib/minimal-json.jar \
  my_script.py
```

------

# 使用适用于 Apache Spark 的 Amazon Redshift 集成进行身份验证
<a name="emr-spark-redshift-auth"></a>

## AWS Secrets Manager 用于检索凭证并连接亚马逊 Redshift
<a name="emr-spark-redshift-secrets"></a>

以下代码示例显示了如何使用检索凭证， AWS Secrets Manager 以便通过 Python 中的 Apache Spark PySpark 接口连接到 Amazon Redshift 集群。

```
from pyspark.sql import SQLContext
import boto3

sc = # existing SparkContext
sql_context = SQLContext(sc)

secretsmanager_client = boto3.client('secretsmanager')
secret_manager_response = secretsmanager_client.get_secret_value(
    SecretId='string',
    VersionId='string',
    VersionStage='string'
)
username = # get username from secret_manager_response
password = # get password from secret_manager_response
url = "jdbc:redshift://redshifthost:5439/database?user=" + username + "&password=" + password

# Read data from a table
df = sql_context.read \
    .format("io.github.spark_redshift_community.spark.redshift") \
    .option("url", url) \
    .option("dbtable", "my_table") \
    .option("tempdir", "s3://path/for/temp/data") \
    .load()
```

## 使用 IAM 检索凭证并连接到 Amazon Redshift
<a name="emr-spark-redshift-iam"></a>

您可以使用 Amazon Redshift 提供的 JDBC 版本 2 驱动程序，通过 Spark 连接器连接到 Amazon Redshift。要使用 AWS Identity and Access Management (IAM)，[请将您的 JDBC 网址配置为使用 IAM 身份验证](https://docs.aws.amazon.com/redshift/latest/mgmt/generating-iam-credentials-configure-jdbc-odbc.html)。要从 Amazon EMR 连接到 Redshift 集群，您必须授予 IAM 角色权限以检索临时 IAM 凭证。将以下权限分配到 IAM 角色，使其能够检索凭证并运行 Amazon S3 操作。
+  [Redshift: GetClusterCredentials](https://docs.aws.amazon.com/redshift/latest/APIReference/API_GetClusterCredentials.html)（适用于预配置的亚马逊 Redshift 集群） 
+  [Redshift: DescribeClusters](https://docs.aws.amazon.com/redshift/latest/APIReference/API_DescribeClusters.html)（适用于预配置的亚马逊 Redshift 集群） 
+ [Redshift：GetWorkgroup](https://docs.aws.amazon.com/redshift-serverless/latest/APIReference/API_GetWorkgroup.html)（适用于亚马逊 Redshift 无服务器工作组）
+  [Redshift：GetCredentials](https://docs.aws.amazon.com/redshift-serverless/latest/APIReference/API_GetCredentials.html)（适用于亚马逊 Redshift 无服务器工作组） 
+  [s3：GetBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_GetBucket.html)
+  [s3：GetBucketLocation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html)
+  [s3：GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)
+  [s3：PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
+  [s3：GetBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html)

有关 `GetClusterCredentials` 的更多信息，请参阅 [`GetClusterCredentials` 的资源策略](https://docs.aws.amazon.com/redshift/latest/mgmt/redshift-iam-access-control-identity-based.html#redshift-policy-resources.getclustercredentials-resources)。

您还必须确保 Amazon Redshift 可以在 `COPY` 和 `UNLOAD` 操作期间担任 IAM 角色。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole"
      ],
      "Resource": "arn:aws:iam::123456789012:role/RedshiftServiceRole",
      "Sid": "AllowSTSAssumerole"
    }
  ]
}
```

------

以下示例在 Spark 和 Amazon Redshift 之间使用 IAM 身份验证：

```
from pyspark.sql import SQLContext
import boto3

sc = # existing SparkContext
sql_context = SQLContext(sc)

url = "jdbc:redshift:iam://redshift-host:redshift-port/db-name"
iam_role_arn = "arn:aws:iam::account-id:role/role-name"

# Read data from a table
df = sql_context.read \
    .format("io.github.spark_redshift_community.spark.redshift") \
    .option("url", url) \
    .option("aws_iam_role", iam_role_arn) \
    .option("dbtable", "my_table") \
    .option("tempdir", "s3a://path/for/temp/data") \
    .mode("error") \
    .load()
```

# 在 Amazon Redshift 中进行读取和写入
<a name="emr-spark-redshift-readwrite"></a>

以下代码示例用于使用 PySpark 数据源 API 和 sparkSQL 读取和写入带有 Amazon Redshift 数据库的示例数据。

------
#### [ Data source API ]

使用 PySpark 数据源 API 从 Amazon Redshift 数据库读取和写入示例数据。

```
import boto3
from pyspark.sql import SQLContext

sc = # existing SparkContext
sql_context = SQLContext(sc)

url = "jdbc:redshift:iam://redshifthost:5439/database"
aws_iam_role_arn = "arn:aws:iam::accountID:role/roleName"

df = sql_context.read \
    .format("io.github.spark_redshift_community.spark.redshift") \
    .option("url", url) \
    .option("dbtable", "tableName") \
    .option("tempdir", "s3://path/for/temp/data") \
    .option("aws_iam_role", "aws_iam_role_arn") \
    .load()

df.write \
    .format("io.github.spark_redshift_community.spark.redshift") \
    .option("url", url) \
    .option("dbtable", "tableName_copy") \
    .option("tempdir", "s3://path/for/temp/data") \
    .option("aws_iam_role", "aws_iam_role_arn") \
    .mode("error") \
    .save()
```

------
#### [ SparkSQL ]

 PySpark 用于通过 sparkSQL 读取和写入亚马逊 Redshift 数据库的示例数据。

```
import boto3
import json
import sys
import os
from pyspark.sql import SparkSession

spark = SparkSession \
    .builder \
    .enableHiveSupport() \
    .getOrCreate()
    
url = "jdbc:redshift:iam://redshifthost:5439/database"
aws_iam_role_arn = "arn:aws:iam::accountID:role/roleName"
    
bucket = "s3://path/for/temp/data"
tableName = "tableName" # Redshift table name

s = f"""CREATE TABLE IF NOT EXISTS {tableName} (country string, data string) 
    USING io.github.spark_redshift_community.spark.redshift 
    OPTIONS (dbtable '{tableName}', tempdir '{bucket}', url '{url}', aws_iam_role '{aws_iam_role_arn}' ); """

spark.sql(s)
         
columns = ["country" ,"data"]
data = [("test-country","test-data")]
df = spark.sparkContext.parallelize(data).toDF(columns)

# Insert data into table
df.write.insertInto(tableName, overwrite=False)
df = spark.sql(f"SELECT * FROM {tableName}")
df.show()
```

------

# 使用 Spark 连接器时的注意事项和限制
<a name="emr-spark-redshift-considerations"></a>
+ 建议您为从 Spark on Amazon EMR 到 Amazon Redshift 的 JDBC 连接启用 SSL。
+ 作为最佳实践，建议您在 AWS Secrets Manager 中管理 Amazon Redshift 集群的凭证。有关示例 [AWS Secrets Manager ，请参阅使用检索连接至亚马逊 Redshift 的凭证](https://docs.aws.amazon.com/redshift/latest/mgmt/redshift-secrets-manager-integration.html)。
+ 建议使用参数 `aws_iam_role` 为 Amazon Redshift 身份验证参数传递 IAM 角色。
+ `tempdir` URI 指向 Amazon S3 位置。此临时目录不会自动清理，因此可能会增加额外成本。
+ 请考虑以下针对 Amazon Redshift 的建议：
  + 建议阻止对 Amazon Redshift 集群的公有访问。
  + 建议启用 [Amazon Redshift 审计日志记录](https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html)。
  + 建议启用 [Amazon Redshift 静态加密](https://docs.aws.amazon.com/redshift/latest/mgmt/security-server-side-encryption.html)。
+ 请考虑以下针对 Amazon S3 的建议：
  + 建议[阻止对 Amazon S3 存储桶的公有访问](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html)。
  + 建议使用 [Amazon S3 服务器端加密](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html)以加密使用的 Amazon S3 存储桶。
  + 建议使用 [Amazon S3 生命周期策略](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)定义 Amazon S3 存储桶的保留规则。
  + Amazon EMR 始终验证从开源导入到映像中的代码。出于安全原因，我们不支持从 Spark 到 Amazon S3 的以下身份验证方法：
    + 在`hadoop-env`配置分类中设置 AWS 访问密钥
    + 在 `tempdir` URI 中对 AWS 访问密钥进行编码

有关使用连接器及其支持参数的更多信息，请参阅以下资源：
+ *Amazon Redshift Management Guide*（《Amazon Redshift 管理指南》）中的 [Amazon Redshift integration for Apache Spark](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)（适用于 Apache Spark 的 Amazon Redshift 集成）
+ Github 上的 [`spark-redshift` 社区存储库](https://github.com/spark-redshift-community/spark-redshift#readme)

# Spark 发行历史记录
<a name="Spark-release-history"></a>

下表列出了 Amazon EMR 每个发行版中包含的 Spark 的版本，以及随应用程序一起安装的组件。有关每个发行版本中的组件版本，请参阅 [Amazon EMR 7.x 发行版](emr-release-7x.md)、[Amazon EMR 6.x 发行版](emr-release-6x.md) 或 [Amazon EMR 5.x 发行版](emr-release-5x.md) 中的发行版“组件版本”部分。

**重要**  
Apache Spark 版本 2.3.1（从 Amazon EMR 发行版 5.16.0 开始提供）解决了 [CVE-2018-8024](https://nvd.nist.gov/vuln/detail/CVE-2018-8024) 和 [CVE-2018-1334](https://nvd.nist.gov/vuln/detail/CVE-2018-1334) 问题。建议您将 Spark 的早期版本迁移到 Spark 2.3.1 版本或更高版本。


**Spark 版本信息**  

| Amazon EMR 发行版标签 | Spark 版本 | 随 Spark 安装的组件 | 
| --- | --- | --- | 
| emr-7.12.0 | 3.5.6-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-hdfs-zkfc, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.11.0 | 3.5.6-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-hdfs-zkfc, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.10.0 | 3.5.5-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.9.0 | 3.5.5-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.8.0 | 3.5.4-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.7.0 | 3.5.3-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.6.0 | 3.5.3-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.5.0 | 3.5.2-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.4.0 | 3.5.2-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.3.0 | 3.5.1-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.2.0 | 3.5.1-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.36.2 | 2.4.8-amzn-2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.1.0 | 3.5.0-amzn-1 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-7.0.0 | 3.5.0-amzn-0 | delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.15.0 | 3.4.1-amzn-2 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.14.0 | 3.4.1-amzn-1 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.13.0 | 3.4.1-amzn-0 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.12.0 | 3.4.0-amzn-0 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.11.1 | 3.3.2-amzn-0.1 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.11.0 | 3.3.2-amzn-0 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.10.1 | 3.3.1-amzn-0.1 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.10.0 | 3.3.1-amzn-0 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.9.1 | 3.3.0-amzn-1.1 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.9.0 | 3.3.0-amzn-1 | aws-sagemaker-spark-sdk, delta, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.8.1 | 3.3.0-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.8.0 | 3.3.0-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.7.0 | 3.2.1-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.36.1 | 2.4.8-amzn-2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.36.0 | 2.4.8-amzn-2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.6.0 | 3.2.0-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.35.0 | 2.4.8-amzn-1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.5.0 | 3.1.2-amzn-1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, iceberg, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.4.0 | 3.1.2-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.3.1 | 3.1.1-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.3.0 | 3.1.1-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.2.1 | 3.0.1-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.2.0 | 3.0.1-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.1.1 | 3.0.0-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.1.0 | 3.0.0-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.0.1 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-6.0.0 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.34.0 | 2.4.8-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.33.1 | 2.4.7-amzn-1.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.33.0 | 2.4.7-amzn-1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.32.1 | 2.4.7-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.32.0 | 2.4.7-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.31.1 | 2.4.6-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.31.0 | 2.4.6-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, hudi-spark, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.30.2 | 2.4.5-amzn-0.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.30.1 | 2.4.5-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.30.0 | 2.4.5-amzn-0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-notebook-env, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.29.0 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.28.1 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.28.0 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, hudi, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.27.1 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.27.0 | 2.4.4 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.26.0 | 2.4.3 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.25.0 | 2.4.3 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.24.1 | 2.4.2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.24.0 | 2.4.2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.23.1 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.23.0 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.22.0 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.21.2 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.21.1 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.21.0 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.20.1 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.20.0 | 2.4.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.19.1 | 2.3.2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.19.0 | 2.3.2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.18.1 | 2.3.2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.18.0 | 2.3.2 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, nginx, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.17.2 | 2.3.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.17.1 | 2.3.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.17.0 | 2.3.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, emr-s3-select, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.16.1 | 2.3.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.16.0 | 2.3.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.15.1 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.15.0 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.14.2 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.14.1 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.14.0 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.13.1 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.13.0 | 2.3.0 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, r, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.12.3 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.12.2 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.12.1 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.12.0 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.11.4 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.11.3 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.11.2 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.11.1 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.11.0 | 2.2.1 | aws-sagemaker-spark-sdk, emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.10.1 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.10.0 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, livy-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.9.1 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.9.0 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.8.3 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.8.2 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.8.1 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.8.0 | 2.2.0 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.7.1 | 2.1.1 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.7.0 | 2.1.1 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.6.1 | 2.1.1 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.6.0 | 2.1.1 | emrfs, emr-goodies, emr-ddb, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, hadoop-yarn-timeline-server, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.5.4 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.5.3 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.5.2 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.5.1 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.5.0 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.4.1 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.4.0 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.3.2 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.3.1 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.3.0 | 2.1.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.2.3 | 2.0.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.2.2 | 2.0.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.2.1 | 2.0.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.2.0 | 2.0.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.1.1 | 2.0.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.1.0 | 2.0.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.0.3 | 2.0.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.0.2 | 2.0.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.0.1 | 2.0.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-5.0.0 | 2.0.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.9.6 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.9.5 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.9.4 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.9.3 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.9.2 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.9.1 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.8.5 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.8.4 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.8.3 | 1.6.3 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.8.2 | 1.6.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.8.1 | 1.6.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.8.0 | 1.6.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.7.4 | 1.6.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.7.3 | 1.6.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.7.2 | 1.6.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.7.1 | 1.6.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.7.0 | 1.6.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-kms-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.6.1 | 1.6.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.6.0 | 1.6.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.5.0 | 1.6.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.4.0 | 1.6.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.3.0 | 1.6.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.2.0 | 1.5.2 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.1.0 | 1.5.0 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-library, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 
| emr-4.0.0 | 1.4.1 | emrfs, emr-goodies, hadoop-client, hadoop-hdfs-datanode, hadoop-hdfs-namenode, hadoop-httpfs-server, hadoop-yarn-nodemanager, hadoop-yarn-resourcemanager, spark-client, spark-history-server, spark-on-yarn, spark-yarn-slave | 

# 在 Amazon EMR 中使用物化视图
<a name="emr-spark-materialized-views"></a>

亚马逊 EMR 7.12.0 及更高版本支持在 Glue 数据目录中创建和管理 Apache Iceberg 物化视图。 AWS 实体化视图是一种托管表，该表以 Apache Iceberg 格式存储 SQL 查询预先计算的结果，并随着基础源表的更改而增量更新。可以使用实体化视图来简化数据转换管道并提高复杂分析工作负载的查询性能。

当您在 Amazon EMR 上使用 Spark 创建物化视图时，视图定义和元数据存储在 AWS Glue 数据目录中。预先计算的结果以 Apache Iceberg 表的形式存储在您的账户中的 Amazon S3 表存储桶或一般用途存储桶中的 Amazon S3 通用存储桶中。 AWS AWS Glue 数据目录使用托管计算基础架构自动监控源表并刷新物化视图。

**Topics**
+ [物化视图如何与 Amazon EMR 配合使用](#emr-spark-materialized-views-how-it-works)
+ [先决条件](#emr-spark-materialized-views-prerequisites)
+ [将 Spark 配置为使用实体化视图](#emr-spark-materialized-views-configure)
+ [创建实体化视图](#emr-spark-materialized-views-create)
+ [查询实体化视图](#emr-spark-materialized-views-query)
+ [刷新实体化视图](#emr-spark-materialized-views-refresh)
+ [管理实体化视图](#emr-spark-materialized-views-manage)
+ [实体化视图的权限](#emr-spark-materialized-views-permissions)
+ [监控实体化视图操作](#emr-spark-materialized-views-monitoring)
+ [示例：完整工作流程](#emr-spark-materialized-views-example)
+ [注意事项和限制](#emr-spark-materialized-views-limitations)

## 物化视图如何与 Amazon EMR 配合使用
<a name="emr-spark-materialized-views-how-it-works"></a>

通过 Apache Spark 的 Iceberg 支持，物化视图与 Amazon EMR 集成。将 Spark 会话配置为使用 AWS Glue 数据目录时，您可以使用标准 SQL 语法创建物化视图。当实体化视图提供更好的性能时，Spark 优化器可以自动重写查询进而使用这些视图，从而无需手动修改应用程序代码。

 AWS Glue 数据目录处理物化视图维护的所有操作方面，包括：
+ 使用 Apache Iceberg 的元数据层检测源表中的更改
+ 使用托管的 Spark 计算计划和执行刷新操作
+ 根据数据更改确定是执行完全刷新还是增量刷新
+ 以 Apache Iceberg 格式存储预先计算的结果，便于多引擎访问

您可以使用与常规表相同的 Spark SQL 接口从 Amazon EMR 中查询物化视图。也可以从其他服务访问预先计算的数据，包括 Amazon Athena 和 Amazon Redshift。

## 先决条件
<a name="emr-spark-materialized-views-prerequisites"></a>

要在 Amazon EMR 中使用物化视图，您需要：
+ 一个 AWS 账户
+ 运行 7.12.0 或更高版本的 Amazon EMR 集群
+ 在 Glue 数据目录中注册的 Apache Iceberg 格式的 AWS 源表
+ AWS 为源表和目标数据库配置的 Lake Formation 权限
+ 在 La AWS ke Formation 中注册的 S3 表存储桶或 S3 通用存储桶，用于存储物化视图数据

## 将 Spark 配置为使用实体化视图
<a name="emr-spark-materialized-views-configure"></a>

要创建和管理物化视图，请使用所需的 Iceberg 扩展和目录设置来配置 Spark 会话。配置会有所不同，具体取决于您的源表和实例化视图使用 S3 表存储桶还是 S3 通用存储桶。

### 为 S3 表进行配置
<a name="emr-spark-materialized-views-configure-s3-tables"></a>

使用 S3 Tables 存储桶作为物化视图时，请为源表和实例化视图配置单独的目录引用：

```
spark-sql \
  --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
  --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.glue_catalog.type=glue \
  --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \
  --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \
  --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \
  --conf spark.sql.catalog.glue_catalog.glue.account-id=111122223333 \
  --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \
  --conf spark.sql.catalog.s3t_catalog=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.s3t_catalog.type=glue \
  --conf spark.sql.catalog.s3t_catalog.glue.id=111122223333:s3tablescatalog/my-table-bucket \
  --conf spark.sql.catalog.s3t_catalog.glue.account-id=111122223333 \
  --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \
  --conf spark.sql.catalog.s3t_catalog.warehouse=s3://amzn-s3-demo-bucket/mv-warehouse \
  --conf spark.sql.catalog.s3t_catalog.glue.region=us-east-1 \
  --conf spark.sql.defaultCatalog=s3t_catalog \
  // turn on automatic query rewrite (optional)
  --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true
```

### 为 S3 通用存储桶进行配置
<a name="emr-spark-materialized-views-configure-s3-general"></a>

使用 S3 通用存储桶时，请配置单个目录引用：

```
spark-sql \
  --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
  --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.glue_catalog.type=glue \
  --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \
  --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \
  --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \
  --conf spark.sql.catalog.s3t_catalog.glue.account-id=111122223333 \
  --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \
  --conf spark.sql.defaultCatalog=glue_catalog \
  // turn on automatic query rewrite (optional)
  --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true
```

### 启用增量刷新
<a name="emr-spark-materialized-views-configure-incremental"></a>

要启用增量刷新优化，请在 Spark 会话中添加以下配置属性：

```
spark-sql \
  --conf spark.sql.optimizer.incrementalMVRefresh.enabled=true \
```

### 配置参数
<a name="emr-spark-materialized-views-configure-parameters"></a>

以下配置参数控制实体化视图的行为：
+ `spark.sql.extensions` – 启用支持实体化视图所需的 Iceberg Spark 会话扩展。
+ `spark.sql.optimizer.answerQueriesWithMVs.enabled` – 启用自动查询重写，进而使用实体化视图 设置为 true 可激活此优化。
+ `spark.sql.optimizer.incrementalMVRefresh.enabled` – 启用增量刷新优化。设置为 true 可在刷新操作期间仅处理更改的数据。

## 创建实体化视图
<a name="emr-spark-materialized-views-create"></a>

您可以使用创建物化视图 SQL 语句创建实例化视图。视图定义将转换逻辑指定为引用一个或多个源表的 SQL 查询。

### DLLs
<a name="emr-spark-materialized-views-create-dlls"></a>

**创建视图**

```
{ CREATE OR REPLACE MATERIALIZED VIEW | CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] }
   view_identifier
  [ view_clauses ]
  [ schedule_clauses ]
  AS [ select_statement ]

view_clauses =
  { [ LOCATION location ] |
    [ PARTITIONED BY (col [, ...]) ] |
    [ COMMENT view_comment ] |
    [ SCHEDULE [ REFRESH ] schedule_clause ] }

schedule_clause =
  { EVERY number { HOUR | HOURS | DAY | DAYS | WEEK | WEEKS } }
```

**注意**  
视图子句必须出现在选择语句之前。

### 创建基本的物化视图
<a name="emr-spark-materialized-views-create-basic"></a>

以下示例创建了一个按客户聚合订单数据的物化视图，在视图定义中使用具有三部分命名约定的完全限定表名：

```
CREATE MATERIALIZED VIEW customer_orders
AS 
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM glue_catalog.sales.orders
GROUP BY customer_name;
```

### 创建具有自动刷新功能的实体化视图
<a name="emr-spark-materialized-views-create-auto-refresh"></a>

要配置自动刷新，请在创建视图时使用完全限定的表名指定刷新计划，视图定义中有三部分命名约定：

```
CREATE MATERIALIZED VIEW customer_orders
SCHEDULE REFRESH EVERY 1 HOUR
AS 
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM glue_catalog.sales.orders
GROUP BY customer_name;
```

### 创建具有跨目录引用的实体化视图
<a name="emr-spark-materialized-views-create-cross-catalog"></a>

当源表与实体化视图位于不同的目录中时，请在视图名称和视图定义中使用具有三部分命名约定的完全限定表名：

```
CREATE MATERIALIZED VIEW s3t_catalog.analytics.customer_summary
AS 
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM glue_catalog.sales.orders
GROUP BY customer_name;
```

## 查询实体化视图
<a name="emr-spark-materialized-views-query"></a>

创建实例化视图后，您可以像使用标准的 SQL SELECT 语句一样查询该视图：

```
SELECT * FROM customer_orders;
```

### 自动查询重写
<a name="emr-spark-materialized-views-query-rewrite"></a>

启用自动查询重写后，Spark 优化器会分析您的查询，并在实体化视图可以提高性能时自动使用这些视图。例如，如果执行以下查询：

```
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM orders
GROUP BY customer_name;
```

只要实体化视图是最新的，Spark 优化器就会自动重写此查询，进而使用 customer\$1orders 实体化视图而不是处理基本订单表。

### 验证自动查询重写
<a name="emr-spark-materialized-views-query-verify"></a>

要验证查询是否使用自动查询重写，请使用 EXPLAIN EXTENDED 命令：

```
EXPLAIN EXTENDED
SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount 
FROM orders
GROUP BY customer_name;
```

在执行计划中，在 BatchScan操作中查找实例化视图的名称。如果计划显示 g BatchScan lue\$1catalog.analytics.customer\$1orders 而不是 glue\$1catalog.s BatchScan ales.orders，则查询已被自动重写为使用实体化视图。

**注意**  
创建物化视图后，自动查询重写需要一段时间才能填充 Spark 元数据缓存。该过程通常在 30 秒内完成。

## 刷新实体化视图
<a name="emr-spark-materialized-views-refresh"></a>

可以使用两种方法刷新实体化视图：完全刷新或增量刷新。完全刷新会根据所有基表数据重新计算整个实体化视图，而增量刷新仅处理自上次刷新以来发生更改的数据。

### 手动完全刷新
<a name="emr-spark-materialized-views-refresh-full"></a>

要对实体化视图进行完全刷新，请执行以下操作：

```
REFRESH MATERIALIZED VIEW customer_orders FULL;
```

执行此命令后，查询实例化视图以验证更新的结果：

```
SELECT * FROM customer_orders;
```

### 手动增量刷新
<a name="emr-spark-materialized-views-refresh-incremental"></a>

要进行增量刷新，请确保在 Spark 会话配置中启用增量刷新，然后执行：

```
REFRESH MATERIALIZED VIEW customer_orders;
```

 AWS Glue 数据目录会根据视图定义和更改的数据量自动确定增量刷新是否适用。如果无法进行增量刷新，则操作将回退为完全刷新。

### 验证增量刷新执行情况
<a name="emr-spark-materialized-views-refresh-verify"></a>

要确认增量刷新已成功执行，您可以通过运行以下命令来检查`lastRefreshType`表的属性：

```
SHOW TBLPROPERTIES <mvName>("lastRefreshType")
```

此外，这也可以通过修改 Spark 日志配置来启用调试日志记录来实现：

1. 打开 Spark log4j 配置文件：

   ```
   sudo vim /usr/lib/spark/conf/log4j2.properties
   ```

1. 添加以下记录器配置：

   ```
   logger.spark.name = org.apache.spark.sql
   logger.spark.level = debug
   
   logger.inmemcache.name = org.apache.spark.sql.InMemMvMetadataCache
   logger.inmemcache.level = off
   ```

1. 执行刷新操作后，在 Spark 输出中搜索以下消息：

   ```
   DEBUG RefreshMaterializedViewExec: Executed Incremental Refresh
   ```

## 管理实体化视图
<a name="emr-spark-materialized-views-manage"></a>

Amazon EMR 提供了用于管理物化视图生命周期的 SQL 命令。

### 描述实体化视图
<a name="emr-spark-materialized-views-manage-describe"></a>

要查看有关实体化视图的元数据，包括其定义、刷新状态和上次刷新时间戳，请执行以下操作：

```
DESCRIBE EXTENDED customer_orders;
```

### 更改实体化视图
<a name="emr-spark-materialized-views-manage-alter"></a>

要修改现有实体化视图的刷新计划，请执行以下操作：

```
ALTER MATERIALIZED VIEW customer_orders 
ADD SCHEDULE REFRESH EVERY 2 HOURS;
```

要移除自动刷新，请执行以下操作：

```
ALTER MATERIALIZED VIEW customer_orders 
DROP SCHEDULE;
```

### 删除实体化视图
<a name="emr-spark-materialized-views-manage-drop"></a>

要删除实体化视图，请执行以下操作：

```
DROP MATERIALIZED VIEW customer_orders;
```

此命令从 AWS Glue 数据目录中删除实例化视图定义，并从 S3 存储桶中删除底层 Iceberg 表数据。

## 实体化视图的权限
<a name="emr-spark-materialized-views-permissions"></a>

要创建和管理物化视图，必须配置 AWS Lake Formation 权限。创建实体化视图的 IAM 角色（定义者角色）需要对源表和目标数据库的特定权限。

### 定义者角色所需的权限
<a name="emr-spark-materialized-views-permissions-definer"></a>

定义者角色必须具有以下 Lake Formation 权限：
+ 在源表上 – 不带行、列或单元格筛选条件的 SELECT 或 ALL 权限
+ 在目标数据库上 – CREATE\$1TABLE 权限
+ 在 AWS Glue 数据目录上 — GetTable 以及 CreateTable API 权限

创建实体化视图时，定义者角色的 ARN 存储在视图定义中。 AWS Glue 数据目录在执行自动刷新操作时扮演此角色。如果定义者角色失去对源表的访问权限，则在恢复权限之前，刷新操作将失败。

### 授予对实体化视图的访问权限
<a name="emr-spark-materialized-views-permissions-access"></a>

要向其他用户授予查询物化视图的权限，请使用 AWS Lake Formation 授予对物化视图表的 SELECT 权限。用户无需直接访问基础源表即可查询实体化视图。

有关配置 Lake Formation 权限的详细信息，请参阅 La AWS ke Formation 开发者指南中的授予和撤消数据目录资源的权限。

## 监控实体化视图操作
<a name="emr-spark-materialized-views-monitoring"></a>

 AWS Glue 数据目录将物化视图刷新操作的指标和日志发布到 Amazon CloudWatch。您可以监控刷新状态、持续时间和通过 CloudWatch 指标处理的数据量。

### 查看刷新指标
<a name="emr-spark-materialized-views-monitoring-metrics"></a>

要查看实体化视图刷新度量，请执行以下操作：

1. 打开控制 CloudWatch 台。

1. 从导航窗格中选择 “指标”。

1. 选择 Glue 命名空间。

1. 按物化视图名称筛选指标。

### 设置警报
<a name="emr-spark-materialized-views-monitoring-alarms"></a>

要在刷新操作失败或超过预期持续时间时收到通知，请针对物化视图指标创建 CloudWatch 警报。您还可以配置 Amazon EventBridge 规则以触发对刷新事件的自动响应。

## 示例：完整工作流程
<a name="emr-spark-materialized-views-example"></a>

以下示例演示了在 Amazon EMR 上创建和使用物化视图的完整工作流程。

1. 使用 SSH 连接到您的 EMR 集群主节点。

1. 使用示例数据创建基表：

   ```
   spark-sql \
     --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
     --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog \
     --conf spark.sql.catalog.glue_catalog.type=glue \
     --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \
     --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \
     --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \
     --conf spark.sql.catalog.glue_catalog.glue.account-id=111122223333 \
     --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \
     --conf spark.sql.defaultCatalog=glue_catalog \
     --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true 
   
   
   CREATE DATABASE IF NOT EXISTS sales;
   
   USE sales;
   
   CREATE TABLE orders (
       id INT,
       customer_name STRING,
       amount DECIMAL(10,2),
       order_date DATE
   );
   
   INSERT INTO orders VALUES 
       (1, 'John Doe', 150.00, DATE('2024-01-15')),
       (2, 'Jane Smith', 200.50, DATE('2024-01-16')),
       (3, 'Bob Johnson', 75.25, DATE('2024-01-17'));
   ```

1. 创建物化视图：

   ```
   CREATE MATERIALIZED VIEW customer_summary
   AS 
   SELECT 
       customer_name, 
       COUNT(*) as order_count, 
       SUM(amount) as total_amount 
   FROM glue_catalog.sales.orders
   GROUP BY customer_name;
   ```

1. 查询物化视图：

   ```
   SELECT * FROM customer_summary;
   ```

1. 在基表中插入其他数据：

   ```
   INSERT INTO orders VALUES 
       (4, 'Jane Smith', 350.00, DATE('2024-01-18')),
       (5, 'Bob Johnson', 100.25, DATE('2024-01-19'));
   ```

1. 刷新实体化视图：

   ```
   REFRESH MATERIALIZED VIEW customer_summary FULL;
   ```

1. 验证更新的结果：

   ```
   SELECT * FROM customer_summary;
   ```

## 注意事项和限制
<a name="emr-spark-materialized-views-limitations"></a>

在 Amazon EMR 中使用物化视图时，请考虑以下几点：
+ 物化视图要求使用 Amazon EMR 7.12.0 或更高版本。
+ 源表必须是在 G AWS lue 数据目录中注册的 Apache Iceberg 表。Apache Hive、Apache Hudi 和 Linux Foundation Delta Lake 表在发布时不受支持。
+ 源表必须与物化视图位于相同的 AWS 区域和 AWS 帐户中。
+ 所有源表都必须由 AWS Lake Formation 管理。不支持仅限 IAM 权限和混合访问权限。
+ 物化视图不能将 AWS Glue 数据目录视图、多方言视图或其他物化视图引用为源表。
+ 视图定义者角色必须对所有未应用行、列或单元格筛选条件的源表具有完全读取权限（SELECT 或 ALL 权限）。
+ 实体化视图最终与源表保持一致。在刷新窗口期间，查询可能会返回过时数据。执行手动刷新，立即保持一致性。
+ 最小自动刷新间隔为一小时。
+ 增量刷新支持有限的 SQL 操作子集。视图定义必须是单个 B SELECT-FROM-WHERE-GROUP Y-HAVING 块，并且不能包含集合操作、子查询、SELECT 或聚合函数中的 DISTINCT 关键字、窗口函数或 INNER JOIN 以外的联接。
+ 增量刷新不支持用户定义的函数或某些内置函数。仅支持 Spark SQL 内置函数的子集。
+ 查询自动重写仅考虑其定义属于受限 SQL 子集的实体化视图，类似于增量刷新限制。
+ 完全刷新操作会覆盖整个表，并使以前的快照不可用。
+ CREATE MATERIALIZED VIEW 查询中不支持包含除字母数字字符和下划线之外的特殊字符的标识符。
+ 以 \$1\$1ivm 前缀开头的实例化视图列保留供系统使用。 AWS 保留在 future 版本中修改或删除这些列的权利。
+ 实体化视图定义中不支持 SORT BY、LIMIT、OFFSET、CLUSTER BY 和 ORDER BY 子句。
+ 不支持跨区域和跨账户源表。
+ 实体化视图定义中不支持诸如 as rand() 或 current\$1timestamp() 之类的非确定性函数。