

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

# EMR Serverless 的元存储配置
<a name="metastore-config"></a>

*Hive 元存储*是一个集中位置，用于存储表的结构信息，包括架构、分区名称和数据类型。通过 EMR Serverless，请将此表元数据保存在有权访问您的作业的元存储中。

对于 Hive 元存储，您有两个选项：
+  AWS Glue 数据目录
+ 外部 Apache Hive 元存储

## 使用 AWS Glue 数据目录作为元数据库
<a name="glue-metastore"></a>

你可以将 Spark 和 Hive 作业配置为使用 Glue AWS 数据目录作为其元数据库。如果需要持久元存储，或不同应用程序、服务或 AWS 账户应用程序共享元存储，建议使用此配置。有关数据目录的更多信息，请参阅[填充 AWS Glue 数据目录](https://docs.aws.amazon.com/glue/latest/dg/populate-data-catalog.html)。有关 AWS Glue 定价的信息，请参阅 [AWS Glue 定价](https://aws.amazon.com/glue/pricing)。

您可以将 EMR Serverless 作业配置为在与您的应用程序 AWS 账户 相同或不同的应用程序中使用 AWS Glue 数据目录。 AWS 账户

### 配置 AWS Glue 数据目录
<a name="glue-metastore-configure"></a>

要配置数据目录，请选择要使用的 EMR Serverless 应用程序类型。

------
#### [ Spark ]

当你使用 EMR Studio 通过 EMR Serverless Spark 应用程序运行作业时，Glue 数据目录是默认的 AWS 元数据库。

使用 SDKs 或时 AWS CLI，在作业运行的`sparkSubmit`参数`com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory`中将`spark.hadoop.hive.metastore.client.factory.class`配置设置为。下面的示例显示了如何使用 AWS CLI配置数据目录。

```
aws emr-serverless start-job-run \
    --application-id application-id \
    --execution-role-arn job-role-arn \
    --job-driver '{
        "sparkSubmit": {
            "entryPoint": "s3://amzn-s3-demo-bucket/code/pyspark/extreme_weather.py",
            "sparkSubmitParameters": "--conf spark.hadoop.hive.metastore.client.factory.class=com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory --conf spark.driver.cores=1 --conf spark.driver.memory=3g --conf spark.executor.cores=4 --conf spark.executor.memory=3g"
        }
    }'
```

或者，您可以在 Spark 代码中创建新 `SparkSession` 时设置此配置。

```
from pyspark.sql import SparkSession

spark = (
    SparkSession.builder.appName("SparkSQL")
    .config(
        "spark.hadoop.hive.metastore.client.factory.class",
        "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory",
    )
    .enableHiveSupport()
    .getOrCreate()
)

# we can query tables with SparkSQL
spark.sql("SHOW TABLES").show()

# we can also them with native Spark
print(spark.catalog.listTables())
```

------
#### [ Hive ]

对于 EMR Serverless Hive 应用程序，数据目录是默认的元存储。也就是说，当你在 EMR Serverless Hive 应用程序上运行作业时，Hive 在数据目录中以与应用程序相同的形式记录元存储信息。 AWS 账户 您不需要虚拟私有云（VPC）即可将数据目录用作元存储。

要访问 Hive 元数据仓表，请添加为 G AWS lue [设置 IAM 权限中概述的必需 G AWS](https://docs.aws.amazon.com/glue/latest/dg/getting-started-access.html) lue 策略。

------

### 为 EMR Serverless AWS 和 Glue 数据目录配置跨账户访问权限
<a name="glue-metastore-cross-account"></a>

要为 EMR Serverless 设置跨账户访问权限，请先登录以下网站： AWS 账户
+ `AccountA`— 这是您创建了 EMR 无服务器应用程序 AWS 账户 的地方。
+ `AccountB`— 包 AWS 账户 含 AWS Glue 数据目录，你想让 EMR Serverless 作业运行访问该目录。

1. 确保 `AccountB` 中的管理员或其他授权身份将资源策略附加到 `AccountB` 中的数据目录。此策略授予 `AccountA` 特定的跨账户权限，以便对 `AccountB` 目录中的资源执行操作。

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

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": [
           "glue:GetDatabase",
           "glue:CreateDatabase",
           "glue:GetDataBases",
           "glue:CreateTable",
           "glue:GetTable",
           "glue:UpdateTable",
           "glue:DeleteTable",
           "glue:GetTables",
           "glue:GetPartition",
           "glue:GetPartitions",
           "glue:CreatePartition",
           "glue:BatchCreatePartition",
           "glue:GetUserDefinedFunctions"
         ],
         "Resource": [
           "arn:aws:glue:*:123456789012:catalog"
         ],
         "Sid": "AllowGLUEGetdatabase"
       }
     ]
   }
   ```

------

1. 将 IAM 策略添加到 `AccountA` 中的 EMR Serverless 作业运行时角色，以便该角色可以访问 `AccountB` 中的数据目录资源。

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

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": [
           "glue:GetDatabase",
           "glue:CreateDatabase",
           "glue:GetDataBases",
           "glue:CreateTable",
           "glue:GetTable",
           "glue:UpdateTable",
           "glue:DeleteTable",
           "glue:GetTables",
           "glue:GetPartition",
           "glue:GetPartitions",
           "glue:CreatePartition",
           "glue:BatchCreatePartition",
           "glue:GetUserDefinedFunctions"
         ],
         "Resource": [
           "arn:aws:glue:*:123456789012:catalog"
         ],
         "Sid": "AllowGLUEGetdatabase"
       }
     ]
   }
   ```

------

1.  启动作业运行。此步骤略有不同，具体取决于 `AccountA` 的 EMR Serverless 应用程序类型。

------
#### [ Spark ]

   如以下示例所示传递 `sparkSubmitParameters` 中的 `spark.hadoop.hive.metastore.glue.catalogid` 属性。将 *`AccountB-catalog-id`* 替换为 `AccountB` 中数据目录的 ID。

   ```
   aws emr-serverless start-job-run \
   --application-id "application-id" \
   --execution-role-arn "job-role-arn" \
   --job-driver '{
       "sparkSubmit": {
           "entryPoint": "s3://amzn-s3-demo-bucket/scripts/test.py",
            "sparkSubmitParameters": "--conf spark.hadoop.hive.metastore.client.factory.class=com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory --conf spark.hadoop.hive.metastore.glue.catalogid=AccountB-catalog-id --conf spark.executor.cores=1 --conf spark.executor.memory=1g --conf spark.driver.cores=1 --conf spark.driver.memory=1g --conf spark.executor.instances=1"
       }
     }' \
   --configuration-overrides '{
       "monitoringConfiguration": {
       "s3MonitoringConfiguration": {
       "logUri": "s3://amzn-s3-demo-bucket/logs/"
       }
     }
   }'
   ```

------
#### [ Hive ]

   如以下示例所示，在 `hive-site` 分类中设置 `hive.metastore.glue.catalogid` 属性。将 *`AccountB-catalog-id`* 替换为 `AccountB` 中数据目录的 ID。

   ```
   aws emr-serverless start-job-run \
   --application-id "application-id" \
   --execution-role-arn "job-role-arn" \
   --job-driver '{
       "hive": {
       "query": "s3://amzn-s3-demo-bucket/hive/scripts/create_table.sql",
       "parameters": "--hiveconf hive.exec.scratchdir=s3://amzn-s3-demo-bucket/hive/scratch --hiveconf hive.metastore.warehouse.dir=s3://amzn-s3-demo-bucket/hive/warehouse"
       }
   }' \
   --configuration-overrides '{
       "applicationConfiguration": [{
           "classification": "hive-site",
           "properties": {
               "hive.metastore.glue.catalogid": "AccountB-catalog-id"
           }
       }]
   }'
   ```

------

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

您可以在 Hive 脚本`ADD JAR`中 JARs 使用添加辅助工具。有关其他注意事项，请参阅[使用 AWS Glue 数据目录时的注意事项](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hive-metastore-glue.html#emr-hive-glue-considerations-hive)。

# 使用外部 Hive 元存储
<a name="external-metastore"></a>

您可以配置 EMR Serverless Spark 和 Hive 作业，使其连接到外部 Hive 元存储，如 Amazon Aurora 或 Amazon RDS for MySQL。本节介绍了如何设置 Amazon RDS Hive 元存储、配置 VPC 和配置 EMR Serverless 作业以使用外部元存储。

## 创建外部 Hive 元存储
<a name="external-metastore-create"></a>

1. 按照[创建 VPC](https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html#Create-VPC) 中的说明，创建具有私有子网的 Amazon Virtual Private Cloud（Amazon VPC）。

1. 使用新的 Amazon VPC 和私有子网创建 EMR Serverless 应用程序。当您使用 VPC 配置 EMR Serverless 应用程序时，首先会为您指定的每个子网预置一个弹性网络接口。然后，将您指定的安全组附加到该网络接口。这样就可以对应用程序进行访问控制。有关如何设置 VPC 的更多详细信息，请参阅 [为 EMR Serverless 应用程序配置 VPC 访问权限以连接数据](vpc-access.md)。

1. 在 Amazon VPC 的私有子网中创建 MySQL 或 Aurora PostgreSQL 数据库。有关如何创建 Amazon RDS 数据库的信息，请参阅[创建 Amazon RDS 数据库实例](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateDBInstance.html)。

1. 按照[修改 Amazon RDS 数据库实例](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html)中的步骤修改 MySQL 或 Aurora 数据库的安全组，允许来自 EMR Serverless 安全组的 JDBC 连接。为从其中一个 EMR Serverless 安全组到 RDS 安全组的入站流量添加规则。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/emr/latest/EMR-Serverless-UserGuide/external-metastore.html)

## 配置 Spark 选项
<a name="external-metastore-spark"></a>

**使用 JDBC**

要将 EMR Serverless Spark 应用程序配置为连接到基于 Amazon RDS for MySQL 或 Amazon Aurora MySQL 实例的 Hive 元存储，请使用 JDBC 连接。在作业运行的 `spark-submit` 参数中传递带有 `--jars` 的 `mariadb-connector-java.jar`。

```
aws emr-serverless start-job-run \
  --application-id "application-id" \
  --execution-role-arn "job-role-arn" \
  --job-driver '{
        "sparkSubmit": {
            "entryPoint": "s3://amzn-s3-demo-bucket/scripts/spark-jdbc.py",
            "sparkSubmitParameters": "--jars s3://amzn-s3-demo-bucket/mariadb-connector-java.jar 
            --conf spark.hadoop.javax.jdo.option.ConnectionDriverName=org.mariadb.jdbc.Driver 
            --conf spark.hadoop.javax.jdo.option.ConnectionUserName=<connection-user-name> 
            --conf spark.hadoop.javax.jdo.option.ConnectionPassword=<connection-password>
            --conf spark.hadoop.javax.jdo.option.ConnectionURL=<JDBC-Connection-string> 
            --conf spark.driver.cores=2
            --conf spark.executor.memory=10G 
            --conf spark.driver.memory=6G 
            --conf spark.executor.cores=4"
        }
    }' \
    --configuration-overrides '{
        "monitoringConfiguration": {
        "s3MonitoringConfiguration": {
            "logUri": "s3://amzn-s3-demo-bucket/spark/logs/"
        }
    }
}'
```

以下代码示例是一个 Spark 入口点脚本，与 Amazon RDS 上的 Hive 元存储交互。

```
from os.path import expanduser, join, abspath
from pyspark.sql import SparkSession
from pyspark.sql import Row
# warehouse_location points to the default location for managed databases and tables
warehouse_location = abspath('spark-warehouse')
spark = SparkSession \
    .builder \
    .config("spark.sql.warehouse.dir", warehouse_location) \
    .enableHiveSupport() \
    .getOrCreate()
spark.sql("SHOW DATABASES").show()
spark.sql("CREATE EXTERNAL TABLE `sampledb`.`sparknyctaxi`(`dispatching_base_num` string, `pickup_datetime` string, `dropoff_datetime` string, `pulocationid` bigint, `dolocationid` bigint, `sr_flag` bigint) STORED AS PARQUET LOCATION 's3://<s3 prefix>/nyctaxi_parquet/'")
spark.sql("SELECT count(*) FROM sampledb.sparknyctaxi").show()
spark.stop()
```

**使用 thrift 服务**

您可以将 EMR Serverless Hive 应用程序配置为连接到基于 Amazon RDS for MySQL 或 Amazon Aurora MySQL 实例的 Hive 元存储。为此，请在现有 Amazon EMR 集群的主节点上运行 thrift 服务器。如果您已经有一个 Amazon EMR 集群，其中包含用于简化 EMR Serverless 作业配置的 thrift 服务器，则此选项是理想之选。

```
aws emr-serverless start-job-run \
  --application-id "application-id" \
  --execution-role-arn "job-role-arn" \
  --job-driver '{
        "sparkSubmit": {
            "entryPoint": "s3://amzn-s3-demo-bucket/thriftscript.py",
            "sparkSubmitParameters": "--jars s3://amzn-s3-demo-bucket/mariadb-connector-java.jar 
            --conf spark.driver.cores=2
            --conf spark.executor.memory=10G 
            --conf spark.driver.memory=6G 
            --conf spark.executor.cores=4"
        }
    }' \
    --configuration-overrides '{
        "monitoringConfiguration": {
        "s3MonitoringConfiguration": {
            "logUri": "s3://amzn-s3-demo-bucket/spark/logs/"
        }
    }
}'
```

以下代码示例是一个入口点脚本（`thriftscript.py`），使用 thrift 协议连接到 Hive 元存储。请注意，需要将 `hive.metastore.uris` 属性设置为从外部 Hive 元存储读取。

```
from os.path import expanduser, join, abspath
from pyspark.sql import SparkSession
from pyspark.sql import Row
# warehouse_location points to the default location for managed databases and tables
warehouse_location = abspath('spark-warehouse')
spark = SparkSession \
    .builder \
    .config("spark.sql.warehouse.dir", warehouse_location) \
    .config("hive.metastore.uris","thrift://thrift-server-host:thift-server-port") \
    .enableHiveSupport() \
    .getOrCreate()
spark.sql("SHOW DATABASES").show()
spark.sql("CREATE EXTERNAL TABLE sampledb.`sparknyctaxi`( `dispatching_base_num` string, `pickup_datetime` string, `dropoff_datetime` string, `pulocationid` bigint, `dolocationid` bigint, `sr_flag` bigint) STORED AS PARQUET LOCATION 's3://<s3 prefix>/nyctaxi_parquet/'")
spark.sql("SELECT * FROM sampledb.sparknyctaxi").show()
spark.stop()
```

## 配置 Hive 选项
<a name="external-metastore-hive"></a>

**使用 JDBC**

如果要在 Amazon RDS MySQL 或 Amazon Aurora 实例上指定外部 Hive 数据库位置，可以覆盖默认的元存储配置。

**注意**  
在 Hive 中，您可以同时对元存储表执行多次写入。如果在两个作业之间共享元存储信息，请确保不要同时写入同一个元存储表，除非写入同一元存储表的不同分区。

在 `hive-site` 分类中设置以下配置以激活外部 Hive 元存储。

```
{
    "classification": "hive-site",
    "properties": {
        "hive.metastore.client.factory.class": "org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClientFactory",
        "javax.jdo.option.ConnectionDriverName": "org.mariadb.jdbc.Driver",
        "javax.jdo.option.ConnectionURL": "jdbc:mysql://db-host:db-port/db-name",
        "javax.jdo.option.ConnectionUserName": "username",
        "javax.jdo.option.ConnectionPassword": "password"
    }
}
```

**使用 thrift 服务器**

你可以将你的 EMR Serverless Hive 应用程序配置为连接基于亚马逊 RDS for MySQL 或 Amazon Aurora My 的 Hive 元存储库。SQLinstance为此，请在现有 Amazon EMR 集群的主节点上运行 thrift 服务器。如果您已经有一个运行 thrift 服务器的 Amazon EMR 集群，希望使用 EMR Serverless 作业配置，则此选项是理想之选。

在 `hive-site` 分类中设置以下配置，以便 EMR Serverless 可以访问远程 thrift 元存储。请注意，必须将 `hive.metastore.uris` 属性设置为从外部 Hive 元存储读取。

```
{
    "classification": "hive-site",
    "properties": {
        "hive.metastore.client.factory.class": "org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClientFactory",
        "hive.metastore.uris": "thrift://thrift-server-host:thirft-server-port"
    }
}
```

# 在 EMR Serv AWS erless 上使用 Glue 多目录层次结构
<a name="external-metastore-glue-multi"></a>

您可以将 EMR 无服务器应用程序配置为使用 Glue 多目录层次结构 AWS 。以下示例展示了如何在 Glue 多目录层次结构中使用 EMR-S Spark。 AWS 

要了解有关多目录层次结构的更多信息，请参阅 [Amazon EMR 上的 G AWS lue 数据目录中使用 Spark 处理多目录层次结构](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-multi-catalog.html)。

## 使用带有 Iceberg 和 Glue 数据目录的 Redshift 托管存储 (RMS) AWS
<a name="emr-serverless-lf-enable-spark-session-glue"></a>

以下内容演示了如何配置 Spark 以与 Iceberg 的 AWS Glue 数据目录集成：

```
aws emr-serverless start-job-run \
    --application-id application-id \
    --execution-role-arn job-role-arn \
    --job-driver '{
        "sparkSubmit": {
            "entryPoint": "s3://amzn-s3-demo-bucket/myscript.py",
            "sparkSubmitParameters": "--conf spark.sql.catalog.nfgac_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"
        }
    }'
```

集成后来自目录中的表的查询示例：

```
SELECT * FROM my_rms_schema.my_table
```

## 将 Redshift 托管存储 (RMS) 与 Iceberg REST API 和 Glue 数据目录配合使用 AWS
<a name="emr-serverless-lf-enable-spark-session-rest"></a>

以下内容展示了如何将 Spark 配置为与 Iceberg REST 目录配合使用：

```
aws emr-serverless start-job-run \
--application-id application-id \
--execution-role-arn job-role-arn \
--job-driver '{
"sparkSubmit": {
"entryPoint": "s3://amzn-s3-demo-bucket/myscript.py",
    "sparkSubmitParameters": "
    --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.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions"
    }
  }'
```

来自目录中的表的查询示例：

```
SELECT * FROM my_rms_schema.my_table
```

# 使用外部元存储时的注意事项
<a name="external-metastore-considerations"></a>
+ 您可以将与 MariaDB JDBC 兼容的数据库配置为元存储。这些数据库的示例包括 RDS for MariaDB、MySQL 和 Amazon Aurora。
+ 元存储不会自动初始化。如果元存储未使用适合 Hive 版本的架构初始化，请使用 [Hive Schema Tool](https://cwiki.apache.org/confluence/display/Hive/Hive+Schema+Tool)。
+ EMR Serverless 不支持 Kerberos 身份验证。您不能将具有 Kerberos 身份验证的 thrift 元存储服务器与 EMR Serverless Spark 或 Hive 作业一起使用。
+ 您必须配置 VPC 访问才能使用多目录层次结构。