

# AWS Glue for Spark ETL 编程的功能和优化
<a name="aws-glue-programming-general"></a>

以下各部分介绍通常适用于任何语言中的 AWS Glue for Spark ETL（提取、转换和加载）编程的技术和值。

**Topics**
+ [

# AWS Glue for Spark 中适用于 ETL 的连接类型和选项
](aws-glue-programming-etl-connect.md)
+ [

# AWS Glue for Spark 中的输入和输出的数据格式选项
](aws-glue-programming-etl-format.md)
+ [

# 适用于 Spark SQL 作业的 AWS Glue 数据目录支持
](aws-glue-programming-etl-glue-data-catalog-hive.md)
+ [

# 使用作业书签
](programming-etl-connect-bookmarks.md)
+ [

# 在 AWS Glue Studio 外部使用敏感数据检测
](aws-glue-api-sensitive-data-example.md)
+ [

# AWS Glue 可视化任务 API
](visual-job-api-chapter.md)

# AWS Glue for Spark 中适用于 ETL 的连接类型和选项
<a name="aws-glue-programming-etl-connect"></a>

在 AWS Glue for Spark 中，各种 PysPark 和 Scala 方法和转换使用 `connectionType` 参数指定连接类型。它们使用 `connectionOptions` 或 `options` 参数指定连接选项。

`connectionType` 参数可以采用下表中显示的值。下面几个部分介绍每种类型所关联的 `connectionOptions`（或 `options`）参数值。除非另有说明，否则这些参数会在连接用作源或接收器时使用。

有关展示如何设置和使用连接选项的代码示例，请参阅每种连接类型的主页。


| `connectionType` | 连接到 | 
| --- | --- | 
| [dynamodb](aws-glue-programming-etl-connect-dynamodb-home.md) | [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/) 数据库 | 
| [kinesis](aws-glue-programming-etl-connect-kinesis-home.md) | [Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/introduction.html) | 
| [S3](aws-glue-programming-etl-connect-s3-home.md) | [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/) | 
| [documentdb](aws-glue-programming-etl-connect-documentdb-home.md#aws-glue-programming-etl-connect-documentdb) | [Amazon DocumentDB (with MongoDB compatibility)](https://docs.aws.amazon.com/documentdb/latest/developerguide/) 数据库 | 
| [opensearch](aws-glue-programming-etl-connect-opensearch-home.md) | [Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/)。 | 
| [redshift](aws-glue-programming-etl-connect-redshift-home.md) | [Amazon Redshift](https://aws.amazon.com/redshift/) 数据库 | 
| [kafka](aws-glue-programming-etl-connect-kafka-home.md) |  [Kafka](https://kafka.apache.org/) 或 [Amazon Managed Streaming for Apache Kafka](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) | 
| [azurecosmos](aws-glue-programming-etl-connect-azurecosmos-home.md) | Azure Cosmos for NoSQL。 | 
| [azuresql](aws-glue-programming-etl-connect-azuresql-home.md) | Azure SQL。 | 
| [bigquery](aws-glue-programming-etl-connect-bigquery-home.md) | Google BigQuery。 | 
| [mongodb](aws-glue-programming-etl-connect-mongodb-home.md) | [MongoDB](https://www.mongodb.com/what-is-mongodb) 数据库，包括 MongoDB Atlas。 | 
| [sqlserver](aws-glue-programming-etl-connect-jdbc-home.md) |  Microsoft SQL Server 数据库（请参阅[JDBC 连接](aws-glue-programming-etl-connect-jdbc-home.md)） | 
| [mysql](aws-glue-programming-etl-connect-jdbc-home.md) | [MySQL](https://www.mysql.com/) 数据库（请参阅[JDBC 连接](aws-glue-programming-etl-connect-jdbc-home.md)） | 
| [oracle](aws-glue-programming-etl-connect-jdbc-home.md) | [Oracle](https://www.oracle.com/database/) 数据库（请参阅[JDBC 连接](aws-glue-programming-etl-connect-jdbc-home.md)） | 
| [postgresql](aws-glue-programming-etl-connect-jdbc-home.md) |  [PostgreSQL](https://www.postgresql.org/) 数据库（请参阅[JDBC 连接](aws-glue-programming-etl-connect-jdbc-home.md)） | 
| [saphana](aws-glue-programming-etl-connect-saphana-home.md) | SAP HANA。 | 
| [snowflake](aws-glue-programming-etl-connect-snowflake-home.md) | [Snowflake](https://www.snowflake.com/) 数据湖 | 
| [teradata](aws-glue-programming-etl-connect-teradata-home.md) | Teradata Vantage。 | 
| [vertica](aws-glue-programming-etl-connect-vertica-home.md) | Vertica。 | 
| [custom.\$1](#aws-glue-programming-etl-connect-market) | Spark、Athena 或 JDBC 数据存储（请参阅[自定义和 AWS Marketplace connectionType 值](#aws-glue-programming-etl-connect-market)）  | 
| [marketplace.\$1](#aws-glue-programming-etl-connect-market) | Spark、Athena 或 JDBC 数据存储（请参阅[自定义和 AWS Marketplace connectionType 值](#aws-glue-programming-etl-connect-market)）  | 

# DynamoDB 连接
<a name="aws-glue-programming-etl-connect-dynamodb-home"></a>

您可以使用 AWS Glue for Spark 在 AWS Glue 中读取和写入 DynamoDB 中的表。您可以使用附加到您的 AWS Glue 任务的 IAM 权限连接到 DynamoDB。AWS Glue 支持将数据写入其他 AWS 账户的 DynamoDB 表。有关更多信息，请参阅 [跨账户、跨区域访问 DynamoDB 表](aws-glue-programming-etl-dynamo-db-cross-account.md)。

最初的 DynamoDB 连接器使用 Glue DynamicFrame 对象来处理从 DynamoDB 提取的数据。AWSGlue 5.0\$1 推出了新的 [支持 Spark DataFrame 的 DynamoDB 连接器](aws-glue-programming-etl-connect-dynamodb-dataframe-support.md)，其中提供了原生 Spark DataFrame 支持。

除了 AWS Glue DynamoDB ETL 连接器外，您还可以使用 DynamoDB 导出连接器从 DynamoDB 读取数据，该连接器调用 DynamoDB `ExportTableToPointInTime` 请求并将其存储在您提供的 Amazon S3 位置，格式为 [DynamoDB JSON](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataExport.Output.html)。AWS Glue然后，通过从 Amazon S3 导出位置读取数据来创建 DynamicFrame 对象。

DynamoDB 写入器在 AWS Glue 版本 1.0 或更高版本中可用。AWS Glue DynamoDB 导出连接器在 AWS Glue 版本 2.0 或更高版本中可用。新的基于 DataFrame 的 DynamoDB 导出连接器在 AWS Glue 版本 5.0 或更高版本中可用。

有关 DynamoDB 的更多信息，请参阅 [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/) 文档。

**注意**  
DynamoDB ETL 读取器不支持筛选条件或下推谓词。

## 配置 DynamoDB 连接
<a name="aws-glue-programming-etl-connect-dynamodb-configure"></a>

要从 AWS Glue 连接到 DynamoDB，请授予与您的 AWS Glue 任务关联的 IAM 角色与 DynamoDB 交互的权限。有关从 DynamoDB 读取或写入所需权限的更多信息，请参阅 IAM 文档中的 [DynamoDB 的操作、资源和条件键](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazondynamodb.html)。

在以下情况下，您可能需要额外的配置：
+ 使用 DynamoDB 导出连接器时，您需要配置 IAM，以便您的任务可以请求 DynamoDB 表导出。此外，您还需要为导出标识一个 Amazon S3 桶，并在 IAM 中提供适当的权限，以便 DynamoDB 向其写入，以及 AWS Glue 作业从中读取。有关更多信息，请参阅[在 DynamoDB 中请求表导出](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/S3DataExport_Requesting.html)。
+ 如果您的 AWS Glue 任务有特定的 Amazon VPC 连接要求，请使用 `NETWORK` AWS Glue 连接类型提供网络选项。由于对 DynamoDB 的访问由 IAM 授权，因此无需使用 AWS Glue DynamoDB 连接类型。

## 从 DynamoDB 读取和写入 DynamoDB
<a name="aws-glue-programming-etl-connect-dynamodb-read-write"></a>

以下代码示例演示了如何从 DynamoDB 表中读取（通过 ETL 连接器）以及向其写入数据。它们演示了如何从一个表读取数据并将数据写入其他表。

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame.from_options(
    connection_type="dynamodb",
    connection_options={"dynamodb.input.tableName": test_source,
        "dynamodb.throughput.read.percent": "1.0",
        "dynamodb.splits": "100"
    }
)
print(dyf.getNumPartitions())

glue_context.write_dynamic_frame_from_options(
    frame=dyf,
    connection_type="dynamodb",
    connection_options={"dynamodb.output.tableName": test_sink,
        "dynamodb.throughput.write.percent": "1.0"
    }
)

job.commit()
```

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamoDbDataSink
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {

  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType = "dynamodb",
      options = JsonOptions(Map(
        "dynamodb.input.tableName" -> test_source,
        "dynamodb.throughput.read.percent" -> "1.0",
        "dynamodb.splits" -> "100"
      ))
    ).getDynamicFrame()
    
    print(dynamicFrame.getNumPartitions())

    val dynamoDbSink: DynamoDbDataSink =  glueContext.getSinkWithFormat(
      connectionType = "dynamodb",
      options = JsonOptions(Map(
        "dynamodb.output.tableName" -> test_sink,
        "dynamodb.throughput.write.percent" -> "1.0"
      ))
    ).asInstanceOf[DynamoDbDataSink]
    
    dynamoDbSink.writeDynamicFrame(dynamicFrame)

    Job.commit()
  }

}
```

------

## 使用 DynamoDB 导出连接器
<a name="aws-glue-programming-etl-connect-dynamodb-export-connector"></a>

在 DynamoDB 表大小超过 80 GB 时，导出连接器的性能优于 ETL 连接器。此外，鉴于导出请求在 AWS Glue 任务中的 Spark 进程之外执行，您可以启用 [AWS Glue 任务的弹性伸缩](https://docs.aws.amazon.com/glue/latest/dg/auto-scaling.html)以节省导出请求期间的 DPU 使用量。借助导出连接器，您也无需为 Spark 执行程序并行度或 DynamoDB 吞吐量读取百分比配置拆分数。

**注意**  
DynamoDB 对调用 `ExportTableToPointInTime` 请求有特定的要求。有关更多信息，请参阅[在 DynamoDB 中请求表导出](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataExport.Requesting.html)。例如，表需要启用时间点恢复 (PITR) 才能使用此连接器。DynamoDB 连接器还支持在将 DynamoDB 导出到 Amazon S3 时进行 AWS KMS 加密。在 AWS Glue 任务配置中指定安全性配置，将为 DynamoDB 导出启用 AWS KMS 加密。KMS 密钥必须与 Simple Storage Service (Amazon S3) 存储桶位于同一区域。  
请注意，您需要支付 DynamoDB 导出的额外费用和 Simple Storage Service (Amazon S3) 存储成本。任务运行完成后，Simple Storage Service (Amazon S3) 中的导出数据仍然存在，因此您无需其他 DynamoDB 导出即可重复使用这些数据。使用此连接器的一个要求是该表启用了时间点恢复 (PITR)。  
DynamoDB ETL 连接器或导出连接器不支持在 DynamoDB 源应用筛选条件或下推谓词。

以下代码示例演示如何进行读取（通过导出连接器）以及打印分区数量。

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame.from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.export": "ddb",
        "dynamodb.tableArn": test_source,
        "dynamodb.s3.bucket": bucket_name,
        "dynamodb.s3.prefix": bucket_prefix,
        "dynamodb.s3.bucketOwner": account_id_of_bucket,
    }
)
print(dyf.getNumPartitions())

job.commit()
```

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamoDbDataSink
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {

  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType = "dynamodb",
      options = JsonOptions(Map(
        "dynamodb.export" -> "ddb",
        "dynamodb.tableArn" -> test_source,
        "dynamodb.s3.bucket" -> bucket_name,
        "dynamodb.s3.prefix" -> bucket_prefix,
        "dynamodb.s3.bucketOwner" -> account_id_of_bucket,
      ))
    ).getDynamicFrame()
    
    print(dynamicFrame.getNumPartitions())

    Job.commit()
  }

}
```

------

以下示例演示如何从具有 `dynamodb` 分类的 AWS Glue 数据目录表进行读取（通过导出连接器）以及打印分区数量：

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dynamicFrame = glue_context.create_dynamic_frame.from_catalog(
        database=catalog_database,
        table_name=catalog_table_name,
        additional_options={
            "dynamodb.export": "ddb", 
            "dynamodb.s3.bucket": s3_bucket,
            "dynamodb.s3.prefix": s3_bucket_prefix
        }
    )
print(dynamicFrame.getNumPartitions())

job.commit()
```

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamoDbDataSink
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {

  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val dynamicFrame = glueContext.getCatalogSource(
        database = catalog_database,
        tableName = catalog_table_name,
        additionalOptions = JsonOptions(Map(
            "dynamodb.export" -> "ddb", 
            "dynamodb.s3.bucket" -> s3_bucket,
            "dynamodb.s3.prefix" -> s3_bucket_prefix
        ))
    ).getDynamicFrame()
    print(dynamicFrame.getNumPartitions())
)
```

------

## 简化 DynamoDB 导出 JSON 的使用
<a name="etl-connect-dynamodb-traversing-structure"></a>

使用 AWS Glue DynamoDB 导出连接器进行 DynamoDB 导出时会生成具有特定嵌套结构的 JSON 文件。有关更多信息，请参阅[数据对象](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataExport.Output.html)。AWS Glue 提供 DynamicFrame 转换，可以将这些结构解除嵌套，成为易于下游应用程序使用的形式。

您可以通过以下两种方式之一调用该转换。在调用要从 DynamoDB 读取的方法时，您可以使用值 `"true"` 来设置连接选项 `"dynamodb.simplifyDDBJson"`。您也可以将转换作为 AWS Glue 库中独立提供的方法进行调用。

考虑 DynamoDB 导出生成的以下架构：

```
root
|-- Item: struct
|    |-- parentMap: struct
|    |    |-- M: struct
|    |    |    |-- childMap: struct
|    |    |    |    |-- M: struct
|    |    |    |    |    |-- appName: struct
|    |    |    |    |    |    |-- S: string
|    |    |    |    |    |-- packageName: struct
|    |    |    |    |    |    |-- S: string
|    |    |    |    |    |-- updatedAt: struct
|    |    |    |    |    |    |-- N: string
|    |-- strings: struct
|    |    |-- SS: array
|    |    |    |-- element: string
|    |-- numbers: struct
|    |    |-- NS: array
|    |    |    |-- element: string
|    |-- binaries: struct
|    |    |-- BS: array
|    |    |    |-- element: string
|    |-- isDDBJson: struct
|    |    |-- BOOL: boolean
|    |-- nullValue: struct
|    |    |-- NULL: boolean
```

`simplifyDDBJson` 转换会将其简化为：

```
root
|-- parentMap: struct
|    |-- childMap: struct
|    |    |-- appName: string
|    |    |-- packageName: string
|    |    |-- updatedAt: string
|-- strings: array
|    |-- element: string
|-- numbers: array
|    |-- element: string
|-- binaries: array
|    |-- element: string
|-- isDDBJson: boolean
|-- nullValue: null
```

**注意**  
`simplifyDDBJson` 在 AWS Glue 3.0 及更高版本中可用。`unnestDDBJson` 转换还可用于简化 DynamoDB 导出 JSON。我们鼓励用户从 `unnestDDBJson` 转换到 `simplifyDDBJson`。

## 在 DynamoDB 操作中配置并行性
<a name="aws-glue-programming-etl-connect-dynamodb-parallelism"></a>

为了提高性能，可以调整可用于 DynamoDB 连接器的某些参数。在调整并行性参数时，您的目标是最大限度地使用预配置的 AWS Glue 工作线程。然后，如果您需要更高的性能，我们建议您增加 DPU 数量以横向扩展任务。

 使用 ETL 连接器时，可以使用 `dynamodb.splits` 参数更改 DynamoDB 读取操作中的并行性。使用导出连接器进行读取时，不需要为 Spark 执行程序并行度配置拆分数。您可以使用 `dynamodb.output.numParallelTasks` 更改 DynamoDB 写入操作中的并行度。

**使用 DynamoDB ETL 连接器读取**

我们建议您根据任务配置中设置的最大工作线程数和以下 `numSlots` 计算来计算 `dynamodb.splits`。如果自动扩缩，则在该上限之下，实际可用的工作线程数量可能会发生变化。有关设置最大工作线程数量的更多信息，请参阅 [在 AWS Glue 中为 Spark 作业配置作业属性](add-job.md) 中的**工作线程数** (`NumberOfWorkers`)。
+ `numExecutors = NumberOfWorkers - 1`

   就上下文而言，为 Spark 驱动程序保留了一个执行程序；其他执行程序用于处理数据。
+ `numSlotsPerExecutor =`

------
#### [ AWS Glue 3.0 and later versions ]
  + `4`，如果 `WorkerType` 为 `G.1X`
  + `8`，如果 `WorkerType` 为 `G.2X`
  + `16`，如果 `WorkerType` 为 `G.4X`
  + `32`，如果 `WorkerType` 为 `G.8X`

------
#### [ AWS Glue 2.0 and legacy versions ]
  + `8`，如果 `WorkerType` 为 `G.1X`
  + `16`，如果 `WorkerType` 为 `G.2X`

------
+ `numSlots = numSlotsPerExecutor * numExecutors`

我们建议您将 `dynamodb.splits` 设置为可用插槽数量 `numSlots`。

**写入 DynamoDB**

`dynamodb.output.numParallelTasks` 参数用于通过以下计算确定每个 Spark 任务的 WCU：

`permittedWcuPerTask = ( TableWCU * dynamodb.throughput.write.percent ) / dynamodb.output.numParallelTasks`

如果配置准确地表示写入 DynamoDB 的 Spark 任务的数量，则 DynamoDB 写入器将发挥最佳作用。在某些情况下，您可能需要覆盖默认计算以提高写入性能。如果不指定此参数，则每个 Spark 任务允许的 WCU 将自动通过以下公式计算：
+ 
  + `numPartitions = dynamicframe.getNumPartitions()`
  + `numSlots`（如本节前面所定义）
  + `numParallelTasks = min(numPartitions, numSlots)`
+ 示例 1：DPU=10，WorkerType=Standard。输入 DynamicFrame 具有 100 个 RDD 分区。
  + `numPartitions = 100`
  + `numExecutors = (10 - 1) * 2 - 1 = 17`
  + `numSlots = 4 * 17 = 68`
  + `numParallelTasks = min(100, 68) = 68`
+ 示例 2：DPU=10，WorkerType=Standard。输入 DynamicFrame 具有 20 个 RDD 分区。
  + `numPartitions = 20`
  + `numExecutors = (10 - 1) * 2 - 1 = 17`
  + `numSlots = 4 * 17 = 68`
  + `numParallelTasks = min(20, 68) = 20`

**注意**  
旧版 AWS Glue 上的任务和使用标准工作线程的任务需要不同的方法来计算插槽数量。如果您需要对这些任务进行性能调整，我们建议您转换到支持的 AWS Glue 版本。

## DynamoDB 连接选项参考
<a name="aws-glue-programming-etl-connect-dynamodb"></a>

指定与 Amazon DynamoDB 的连接。

源连接和接收器连接的连接选项不同。

### "connectionType": "dynamodb" with the ETL connector as Source
<a name="etl-connect-dynamodb-as-source"></a>

在使用 AWS Glue DynamoDB ETL 连接器时，请使用以下连接选项并将 `"connectionType": "dynamodb"` 作为源：
+ `"dynamodb.input.tableName"`：（必需）要从中读取数据的 DynamoDB 表格。
+ `"dynamodb.throughput.read.percent"`：（可选）要使用的读取容量单位 (RCU) 的百分比。默认设置为“0.5”。可接受的值从“0.1”到“1.5”，包含这两个值。
  + `0.5` 表示默认读取速率，这意味着 AWS Glue 将尝试占用表的一半的读取容量。如果增加值超过 `0.5`，AWS Glue 将增加请求速率；将值降低到 `0.5` 以下将降低读取请求速率。（实际读取速率取决于 DynamoDB 表中是否存在统一键分配的等因素。）
  + 当 DynamoDB 表处于按需模式时，AWS Glue 处理表的读取容量为 40000。要导出大型表，我们建议您将 DynamoDB 表切换为按需模式。
+ `"dynamodb.splits"`：（可选）定义在读取时将此 DynamoDB 表分成多少个部分。默认设置为“1”。可接受的值从“1”到“1,000,000”，包含这两个值。

  `1` 表示没有并行度。我们强烈建议您使用以下公式指定更大的值以获得更好的性能。有关适当设置值的更多信息，请参阅 [在 DynamoDB 操作中配置并行性](#aws-glue-programming-etl-connect-dynamodb-parallelism)。
+ `"dynamodb.sts.roleArn"`：（可选）用于跨账户访问的 IAM 角色 ARN。此参数适用于 AWS Glue 1.0 或更高版本。
+ `"dynamodb.sts.roleSessionName"`：（可选）STS 会话名称。默认设置为“glue-dynamodb-read-sts-session”。此参数适用于 AWS Glue 1.0 或更高版本。

### "connectionType": "dynamodb" with the AWS Glue DynamoDB export connector as Source
<a name="etl-connect-dynamodb-as-source-export-connector"></a>

在使用 AWS Glue DynamoDB 导出连接器（仅适用于 AWS Glue 版本 2.0 以上）时，使用以下连接选项并将 "connectionType": "dynamodb"用作源：
+ `"dynamodb.export"`：（必需）字符串值：
  + 如果设置为 `ddb`，将启用 AWS Glue DynamoDB 导出连接器，其中在 AWS Glue 任务期间将调用新的 `ExportTableToPointInTimeRequest`。新的导出将通过从 `dynamodb.s3.bucket` 和 `dynamodb.s3.prefix` 传递的位置生成。
  + 如果设置为 `s3`，将启用 AWS Glue DynamoDB 导出连接器但会跳过创建新的 DynamoDB 导出，而使用 `dynamodb.s3.bucket` 和 `dynamodb.s3.prefix` 作为该表以前导出的 Simple Storage Service (Amazon S3) 位置。
+ `"dynamodb.tableArn"`：（必需）要从中读取数据的 DynamoDB 表格。
+ `"dynamodb.unnestDDBJson"`：（可选）默认值：false。有效值：布尔值。如果设置为 true（真），则对导出中存在的 DynamoDB JSON 结构执行解除嵌套转换。同时将 `"dynamodb.unnestDDBJson"` 和 `"dynamodb.simplifyDDBJson"` 设置为 true 是错误的。在 AWS Glue 3.0 及更高版本中，我们建议您在简化 DynamoDB Map 类型时使用 `"dynamodb.simplifyDDBJson"` 以获得更好的行为。有关更多信息，请参阅 [简化 DynamoDB 导出 JSON 的使用](#etl-connect-dynamodb-traversing-structure)。
+ `"dynamodb.simplifyDDBJson"`：（可选）默认值：false。有效值：布尔值。如果设置为 true，则执行转换以简化导出中存在的 DynamoDB JSON 结构的架构。这与 `"dynamodb.unnestDDBJson"` 选项的目的相同，但为 DynamoDB 表中的 DynamoDB Map 类型甚至嵌套 Map 类型提供了更好的支持。此选项在 AWS Glue 3.0 及更高版本中可用。同时将 `"dynamodb.unnestDDBJson"` 和 `"dynamodb.simplifyDDBJson"` 设置为 true 是错误的。有关更多信息，请参阅 [简化 DynamoDB 导出 JSON 的使用](#etl-connect-dynamodb-traversing-structure)。
+ `"dynamodb.s3.bucket"`：（可选）指示将会执行 DynamoDB `ExportTableToPointInTime` 进程的 Amazon S3 存储桶位置。导出的文件格式为 DynamoDB JSON。
  + `"dynamodb.s3.prefix"`:（可选）指示将用于存储 DynamoDB `ExportTableToPointInTime` 负载的 Amazon S3 存储桶内的 Amazon S3 前缀位置。如果既未指定 `dynamodb.s3.prefix`，也未指定 `dynamodb.s3.bucket`，则这些值将默认为 AWS Glue 任务配置中指定的临时目录位置。有关更多信息，请参阅 [AWS Glue 使用的特殊参数](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html)。
  + `"dynamodb.s3.bucketOwner"`：指示跨账户 Amazon S3 访问所需的存储桶拥有者。
+ `"dynamodb.sts.roleArn"`：（可选）跨账户访问和/或跨区域访问 DynamoDB 表时将会代入的 IAM 角色 ARN。注意：相同的 IAM 角色 ARN 将用于访问为 `ExportTableToPointInTime` 请求指定的 Amazon S3 位置。
+ `"dynamodb.sts.roleSessionName"`：（可选）STS 会话名称。默认设置为“glue-dynamodb-read-sts-session”。
+ `"dynamodb.exportTime"`（可选）有效值：表示 ISO-8601 瞬时的字符串。应进行导出的时间点。
+ `"dynamodb.sts.region"`：（如果使用区域端点进行跨区域调用，则为必填项）托管要读取的 DynamoDB 表的区域。

### "connectionType": "dynamodb" with the ETL connector as Sink
<a name="etl-connect-dynamodb-as-sink"></a>

将 `"connectionType": "dynamodb"` 用作连接器时可使用以下连接选项：
+ `"dynamodb.output.tableName"`：（必需）要写入的 DynamoDB 表。
+ `"dynamodb.throughput.write.percent"`：（可选）要使用的写入容量单位（WCU）的百分比。默认设置为“0.5”。可接受的值从“0.1”到“1.5”，包含这两个值。
  + `0.5` 表示默认写入速率，这意味着 AWS Glue 将尝试占用表的一半的写入容量。如果增加值超过 0.5，AWS Glue 将增加请求速率；将值降低到 0.5 以下将降低写入请求速率。（实际写入速率取决于 DynamoDB 表中是否存在统一键分配等因素）。
  + 当 DynamoDB 表处于按需模式时，AWS Glue 处理表的写入容量为 `40000`。要导入大型表，我们建议您将 DynamoDB 表切换为按需模式。
+ `"dynamodb.output.numParallelTasks"`：（可选）定义同时向 DynamoDB 写入数据的并行任务数。用于计算每个 Spark 任务的允许 WCU。在大多数情况下，AWS Glue 将为此值计算合理的默认值。有关更多信息，请参阅 [在 DynamoDB 操作中配置并行性](#aws-glue-programming-etl-connect-dynamodb-parallelism)。
+ `"dynamodb.output.retry"`：（可选）定义存在 DynamoDB 中的 `ProvisionedThroughputExceededException` 时我们执行的重试次数。默认设置为“10”。
+ `"dynamodb.sts.roleArn"`：（可选）用于跨账户访问的 IAM 角色 ARN。
+ `"dynamodb.sts.roleSessionName"`：（可选）STS 会话名称。默认设置为“glue-dynamodb-write-sts-session”。

# 跨账户、跨区域访问 DynamoDB 表
<a name="aws-glue-programming-etl-dynamo-db-cross-account"></a>

AWS Glue ETL 任务支持跨账户、跨区域访问 DynamoDB 表。AWS GlueETL 任务支持从其他 AWS 账户的 DynamoDB 表读取数据，并将数据写入其他 AWS 账户的 DynamoDB 表。AWS Glue 还支持从其他区域的 DynamoDB 表读取数据并将数据写入其他区域的 DynamoDB 表。本部分提供关于设置访问的说明以及示例脚本。

本部分的过程参考了用于创建 IAM 角色和授予角色访问权限的 IAM 教程。本教程还讨论了担任角色，但在此处，您将使用任务脚本来担任 AWS Glue 中的角色。本教程还包含有关常规跨账户实践的信息。有关更多信息，请参阅《IAM 用户指南》**中的[教程：使用 IAM 角色委派跨 AWS 账户的访问权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html)。

## 创建角色
<a name="aws-glue-programming-etl-dynamo-db-create-role"></a>

按照[教程中的步骤 1](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html#tutorial_cross-account-with-roles-1) 在账户 A 中创建 IAM 角色。在定义角色的权限时，您可以选择附加现有策略（例如 `AmazonDynamoDBReadOnlyAccess` 或 `AmazonDynamoDBFullAccess`）以允许角色读取/写入 DynamoDB。以下示例演示了如何使用权限策略 `AmazonDynamoDBFullAccess` 创建名为 `DynamoDBCrossAccessRole` 的角色。

## 向角色授予访问权限
<a name="aws-glue-programming-etl-dynamo-db-grant-access"></a>

遵循《IAM 用户指南》**中的[教程中的步骤 2](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html#tutorial_cross-account-with-roles-2)，允许账户 B 切换到新创建的角色。以下示例使用以下语句创建新策略：

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::111122223333:role/DynamoDBCrossAccessRole"
  }
}
```

------

然后，您可以将此策略附加到要用于访问 DynamoDB 的组/角色/用户。

## 担任 AWS Glue 作业脚本中的角色
<a name="aws-glue-programming-etl-dynamo-db-assume-role"></a>

现在，您可以登录账户 B 并创建 AWS Glue 任务。要创建任务，请参阅[在 AWS Glue 中为 Spark 作业配置作业属性](add-job.md)中的说明。

在任务脚本中，您需要使用 `dynamodb.sts.roleArn` 参数担任 `DynamoDBCrossAccessRole` 角色。假设此角色允许您获取临时凭证，这些凭证需要用于访问账户 B 中的 DynamoDB。请查看这些示例脚本。

对于跨区域跨账户读取（ETL 连接器）：

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame_from_options(
    connection_type="dynamodb",
    connection_options={
    "dynamodb.region": "us-east-1",
    "dynamodb.input.tableName": "test_source",
    "dynamodb.sts.roleArn": "<DynamoDBCrossAccessRole's ARN>"
    }
)
dyf.show()
job.commit()
```

对于跨区域跨账户读取（ELT 连接器）：

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame_from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.export": "ddb",
        "dynamodb.tableArn": "<test_source ARN>",
        "dynamodb.sts.roleArn": "<DynamoDBCrossAccessRole's ARN>"
    }
)
dyf.show()
job.commit()
```

对于跨区域的读取和跨账户写入：

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions
 
args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)
 
dyf = glue_context.create_dynamic_frame_from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.region": "us-east-1",
        "dynamodb.input.tableName": "test_source"
    }
)
dyf.show()
 
glue_context.write_dynamic_frame_from_options(
    frame=dyf,
    connection_type="dynamodb",
    connection_options={
        "dynamodb.region": "us-west-2",
        "dynamodb.output.tableName": "test_sink",
        "dynamodb.sts.roleArn": "<DynamoDBCrossAccessRole's ARN>"
    }
)
 
job.commit()
```

# 支持 Spark DataFrame 的 DynamoDB 连接器
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-support"></a>

借助支持 Spark DataFrame 的 DynamoDB 连接器，您可以使用 Spark DataFrame API 在 DynamoDB 中读取和写入表。连接器的设置步骤与基于 DynamicFrame 的连接器的设置步骤相同，可以在[此处](aws-glue-programming-etl-connect-dynamodb-home.md#aws-glue-programming-etl-connect-dynamodb-configure)找到。

要加载基于 DataFrame 的连接器库，请务必将 DynamoDB 连接附加到 Glue 作业。

**注意**  
Glue 控制台 UI 目前不支持创建 DynamoDB 连接。可以使用 Glue CLI（[CreateConnection](https://docs.aws.amazon.com/cli/latest/reference/glue/create-connection.html)）创建 DynamoDB 连接：  

```
        aws glue create-connection \
            --connection-input '{ \
                "Name": "my-dynamodb-connection", \
                "ConnectionType": "DYNAMODB", \
                "ConnectionProperties": {}, \
                "ValidateCredentials": false, \
                "ValidateForComputeEnvironments": ["SPARK"] \
            }'
```

创建 DynamoDB 连接后，可以通过 CLI（[CreateJob](https://docs.aws.amazon.com/cli/latest/reference/glue/create-job.html)、[UpdateJob](https://docs.aws.amazon.com/cli/latest/reference/glue/update-job.html)）或直接在“作业详细信息”页面将其附加到您的 Glue 作业：

![\[alt text not found\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/dynamodb-dataframe-connector.png)


在确保与 DYNAMODB 类型的连接已附加到 Glue 作业后，可以从基于 DataFrame 的连接器使用以下读取、写入和导出操作。

## 使用基于 DataFrame 的连接器读取和写入 DynamoDB
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-read-write"></a>

以下代码示例演示了如何通过基于 DataFrame 的连接器读取和写入 DynamoDB 表。它们演示了如何从一个表读取数据并将数据写入其他表。

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
spark = glueContext.spark_session
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

# Read from DynamoDB
df = spark.read.format("dynamodb") \
    .option("dynamodb.input.tableName", "test-source") \
    .option("dynamodb.throughput.read.ratio", "0.5") \
    .option("dynamodb.consistentRead", "false") \
    .load()

print(df.rdd.getNumPartitions())

# Write to DynamoDB
df.write \
  .format("dynamodb") \
  .option("dynamodb.output.tableName", "test-sink") \
  .option("dynamodb.throughput.write.ratio", "0.5") \
  .option("dynamodb.item.size.check.enabled", "true") \
  .save()

job.commit()
```

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val spark = glueContext.getSparkSession
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    val df = spark.read
      .format("dynamodb")
      .option("dynamodb.input.tableName", "test-source")
      .option("dynamodb.throughput.read.ratio", "0.5")
      .option("dynamodb.consistentRead", "false")
      .load()

    print(df.rdd.getNumPartitions)

    df.write
      .format("dynamodb")
      .option("dynamodb.output.tableName", "test-sink")
      .option("dynamodb.throughput.write.ratio", "0.5")
      .option("dynamodb.item.size.check.enabled", "true")
      .save()

    job.commit()
  }
}
```

------

## 通过基于 DataFrame 的连接器使用 DynamoDB 导出
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-export"></a>

对于大于 80 GB 的 DynamoDB 表大小，最好使用导出操作而不是读取操作。以下代码示例演示了如何通过基于 DataFrame 的连接器读取表、导出到 S3以及打印分区数量。

**注意**  
DynamoDB 导出功能可以通过 Scala `DynamoDBExport` 对象使用。Python 用户可以通过 Spark 的 JVM 互操作进行访问，也可以将适用于 Python 的 Amazon SDK（Boto3）与 DynamoDB `ExportTableToPointInTime` API 一起使用。

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.{GlueArgParser, Job}
import org.apache.spark.SparkContext
import glue.spark.dynamodb.DynamoDBExport
import scala.collection.JavaConverters._

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val spark = glueContext.getSparkSession
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val options = Map(
      "dynamodb.export" -> "ddb",
      "dynamodb.tableArn" -> "arn:aws:dynamodb:us-east-1:123456789012:table/my-table",
      "dynamodb.s3.bucket" -> "my-s3-bucket",
      "dynamodb.s3.prefix" -> "my-s3-prefix",
      "dynamodb.simplifyDDBJson" -> "true"
    )
    val df = DynamoDBExport.fullExport(spark, options)
    
    print(df.rdd.getNumPartitions)
    df.count()
    
    Job.commit()
  }
}
```

------

## 配置选项
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-options"></a>

### 读取选项
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-read-options"></a>


| 选项 | 描述 | 默认 | 
| --- | --- | --- | 
| dynamodb.input.tableName | DynamoDB 表名称（必填） | - | 
| dynamodb.throughput.read | 要使用的读取容量单位（RCU）。如果未指定，则使用 dynamodb.throughput.read.ratio 进行计算。 | - | 
| dynamodb.throughput.read.ratio | 要使用的读取容量单位（RCU）的比率 | 0.5 | 
| dynamodb.table.read.capacity | 用于计算吞吐量的按需表的读取容量。此参数仅在按需容量表中有效。默认为温吞吐量读取单位。 | - | 
| dynamodb.splits | 定义在并行扫描操作中使用的分段数。如果未提供，连接器将计算出合理的默认值。 | - | 
| dynamodb.consistentRead | 是否使用强一致性读取 | FALSE | 
| dynamodb.input.retry | 定义出现可重试异常时我们执行的重试次数。 | 10 | 

### 写入选项
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-write-options"></a>


| 选项 | 描述 | 默认 | 
| --- | --- | --- | 
| dynamodb.output.tableName | DynamoDB 表名称（必填） | - | 
| dynamodb.throughput.write | 要使用的写入容量单位（WCU）。如果未指定，则使用 dynamodb.throughput.write.ratio 进行计算。 | - | 
| dynamodb.throughput.write.ratio | 要使用的写入容量单位（WCU）的比率 | 0.5 | 
| dynamodb.table.write.capacity | 用于计算吞吐量的按需表的写入容量。此参数仅在按需容量表中有效。默认为温吞吐量写入单位。 | - | 
| dynamodb.item.size.check.enabled | 如果为 true，则在写入 DynamoDB 表之前，连接器会计算项目大小，如果大小超过最大大小，则会中止。 | TRUE | 
| dynamodb.output.retry | 定义出现可重试异常时我们执行的重试次数。 | 10 | 

### 导出选项
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-export-options"></a>


| 选项 | 描述 | 默认 | 
| --- | --- | --- | 
| dynamodb.export | 如果设置为 ddb，将启用 AWS Glue DynamoDB 导出连接器，其中在 AWS Glue 作业期间将调用新的 ExportTableToPointInTimeRequet。新的导出将通过从 dynamodb.s3.bucket 和 dynamodb.s3.prefix 传递的位置生成。如果设置为 s3，将启用 AWS Glue DynamoDB 导出连接器，但会跳过创建新的 DynamoDB 导出，而使用 dynamodb.s3.bucket 和 dynamodb.s3.prefix 作为该表以前导出的 Amazon S3 位置。 | ddb | 
| dynamodb.tableArn | 要从中读取数据的 DynamoDB 表。如果将 dynamodb.export 设置为 ddb，则是必需的。 |  | 
| dynamodb.simplifyDDBJson | 如果设置为 true，则执行转换，进而简化导出中存在的 DynamoDB JSON 结构的架构。 | FALSE | 
| dynamodb.s3.bucket | DynamoDB 导出期间用于存储临时数据的 S3 存储桶（必填） |  | 
| dynamodb.s3.prefix | DynamoDB 导出期间用于存储临时数据的 S3 前缀 |  | 
| dynamodb.s3.bucketOwner | 指示跨账户 Amazon S3 访问所需的存储桶拥有者 |  | 
| dynamodb.s3.sse.algorithm | 存储临时数据的存储桶上使用的加密类型。有效值为 AES256 和 KMS。 |  | 
| dynamodb.s3.sse.kmsKeyId | 用于加密存储临时数据的 S3 存储桶的 AWS KMS 托管式密钥的 ID（如果适用）。 |  | 
| dynamodb.exportTime | 应进行导出的时间点。有效值：表示 ISO-8601 瞬时的字符串。 |  | 

### 常规选项
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-general-options"></a>


| 选项 | 描述 | 默认 | 
| --- | --- | --- | 
| dynamodb.sts.roleArn | 用于跨账户访问的 IAM 角色 ARN | - | 
| dynamodb.sts.roleSessionName | STS 会话名称 | glue-dynamodb-sts-session | 
| dynamodb.sts.region | STS 客户端的区域（用于跨区域角色担任） | 与 region 选项相同 | 

# Kinesis 连接
<a name="aws-glue-programming-etl-connect-kinesis-home"></a>

您可以使用 Kinesis 连接来对 Amazon Kinesis Data Streams 执行读取和写入操作，方法是通过存储在 Data Catalog 表中的信息进行读取和写入，或通过提供信息直接访问数据流。您可以从 Kinesis 读取信息到 Spark DataFrame 中，然后将其转换为 AWS Glue DynamicFrame。您可以用 JSON 格式将 DynamicFrames 写入 Kinesis。如果直接访问数据流，请使用这些选项提供有关如何访问数据流的信息。

如果您使用 `getCatalogSource` 或 `create_data_frame_from_catalog` 使用来自 Kinesis 流式处理源的记录，则任务具有数据目录数据库和表名称信息，将其用于获取一些基本参数，以便从 Kinesis 流式处理源读取数据。如果使用 `getSource`、`getSourceWithFormat`、`createDataFrameFromOptions` 或 `create_data_frame_from_options`，则必须使用此处描述的连接选项指定这些基本参数。

您可以使用 `GlueContext` 类中指定方法的以下参数为 Kinesis 指定连接选项。
+ Scala
  + `connectionOptions`：与 `getSource`、`createDataFrameFromOptions`、`getSink` 结合使用 
  + `additionalOptions`：与 `getCatalogSource`、`getCatalogSink` 结合使用
  + `options`：与 `getSourceWithFormat`、`getSinkWithFormat` 结合使用
+ Python
  + `connection_options`：与 `create_data_frame_from_options`、`write_dynamic_frame_from_options` 结合使用
  + `additional_options`：与 `create_data_frame_from_catalog`、`write_dynamic_frame_from_catalog` 结合使用
  + `options`：与 `getSource`、`getSink` 结合使用

有关流式处理 ETL 作业的注意事项和限制，请参阅 [串流 ETL 注释和限制](add-job-streaming.md#create-job-streaming-restrictions)。

## 配置 Kinesis
<a name="aws-glue-programming-etl-connect-kinesis-configure"></a>

要在 AWS Glue Spark 作业中连接到 Kinesis 数据流，需要具备一些先决条件：
+ 如果读取，AWS Glue 作业必须拥有对 Kinesis 数据流的读取访问权限级别 IAM 权限。
+ 如果写入，AWS Glue 作业必须拥有对 Kinesis 数据流的写入访问权限级别 IAM 权限。

在某些情况下，您需要配置其他先决条件：
+ 如果您的 AWS Glue 作业配置了**其他网络连接**（通常用于连接到其他数据集），并且其中一个连接提供 Amazon VPC **网络选项**，则这将引导您的作业通过 Amazon VPC 进行通信。在这种情况下，您还需要将 Kinesis 数据流配置为通过 Amazon VPC 进行通信。您可以通过在 Amazon VPC 和 Kinesis 数据流之间创建接口 VPC 端点实现此目的。有关更多信息，请参阅 [Using Kinesis Data Streams with Interface VPC Endpoints](https://docs.aws.amazon.com//streams/latest/dev/vpc.html)。
+ 在另一个账户中指定 Amazon Kinesis Data Streams 时，您必须设置角色和策略，从而允许跨账户访问。有关更多信息，请参阅[示例：从不同账户的 Kinesis 串流中读取](https://docs.aws.amazon.com/kinesisanalytics/latest/java/examples-cross.html)。

有关流式处理 ETL 作业先决条件的更多信息，请参阅 [在 AWS Glue 中流式处理 ETL 作业](add-job-streaming.md)。

## 示例：从 Kinesis 流读取
<a name="aws-glue-programming-etl-connect-kinesis-read"></a>

### 示例：从 Kinesis 流读取
<a name="section-etl-connect-kinesis-read"></a>

与 [forEachBatch](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-forEachBatch) 结合使用。

Amazon Kinesis 流式处理源示例：

```
kinesis_options =
   { "streamARN": "arn:aws:kinesis:us-east-2:777788889999:stream/fromOptionsStream",
     "startingPosition": "TRIM_HORIZON", 
     "inferSchema": "true", 
     "classification": "json" 
   }
data_frame_datasource0 = glueContext.create_data_frame.from_options(connection_type="kinesis", connection_options=kinesis_options)
```

## 示例：写入 Kinesis 流
<a name="aws-glue-programming-etl-connect-kinesis-write"></a>

### 示例：从 Kinesis 流读取
<a name="section-etl-connect-kinesis-read"></a>

与 [forEachBatch](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-forEachBatch) 结合使用。

Amazon Kinesis 流式处理源示例：

```
kinesis_options =
   { "streamARN": "arn:aws:kinesis:us-east-2:777788889999:stream/fromOptionsStream",
     "startingPosition": "TRIM_HORIZON", 
     "inferSchema": "true", 
     "classification": "json" 
   }
data_frame_datasource0 = glueContext.create_data_frame.from_options(connection_type="kinesis", connection_options=kinesis_options)
```

## Kinesis 连接选项参考
<a name="aws-glue-programming-etl-connect-kinesis"></a>

为 Amazon Kinesis Data Streams 指定连接选项。

为 Kinesis 流式处理数据源使用以下连接选项：
+ `"streamARN"`（必填）用于读/写。Kinesis 数据流的 ARN。
+ `"classification"`（读取所必填）用于读取。记录中数据使用的文件格式。除非 Data Catalog 提供，否则为必需。
+ `"streamName"` –（可选）用于读取。要从中读取的 Kinesis 数据流的名称。与 `endpointUrl` 一起使用。
+ `"endpointUrl"` –（可选）用于读取。默认：“https://kinesis.us-east-1.amazonaws.com”。Kinesis 流的 AWS 端点。除非要连接到特殊区域，否则您无需对此进行更改。
+ `"partitionKey"` –（可选）用于写入。生成记录时所使用的 Kinesis 分区键。
+ `"delimiter"`（可选）用于读取。当 `classification` 为 CSV 时使用的值分隔符。默认为“`,`”。
+ `"startingPosition"`：（可选）用于读取。要从中读取数据的 Kinesis 数据流中的起始位置。可能的值是 `"latest"`、`"trim_horizon"`、`"earliest"` 或以模式 `yyyy-mm-ddTHH:MM:SSZ` 采用 UTC 格式的时间戳字符串（其中 `Z` 表示带有 \$1/-的 UTC 时区偏移量。例如：“2023-04-04T08:00:00-04:00”）。默认值为 `"latest"`。注意：只有 AWS Glue 版本 4.0 或更高版本支持 `"startingPosition"` 的 UTC 格式中的时间戳字符串。
+ `"failOnDataLoss"`：（可选）如果有任何活动分片丢失或已过期，则作业失败。默认值为 `"false"`。
+ `"awsSTSRoleARN"`：（可选）用于读取/写入。要使用 AWS Security Token Service（AWS STS）代入的角色的 Amazon 资源名称（ARN）。此角色必须拥有针对 Kinesis 数据流执行描述或读取记录操作的权限。在访问其他账户中的数据流时，必须使用此参数。与 `"awsSTSSessionName"` 结合使用。
+ `"awsSTSSessionName"`：（可选）用于读取/写入。使用 AWS STS 代入角色的会话的标识符。在访问其他账户中的数据流时，必须使用此参数。与 `"awsSTSRoleARN"` 结合使用。
+ `"awsSTSEndpoint"`：（可选）使用代入角色连接到 Kinesis 时要使用的 AWS STS 端点。这允许在 VPC 中使用区域 AWS STS 端点，而使用默认的全局端点是不可能的。
+ `"maxFetchTimeInMs"`：（可选）用于读取。作业执行程序从 Kinesis 数据流中读取当前批处理记录所花费的最长时间，以毫秒为单位指定。在这段时间内可以进行多次 `GetRecords` API 调用。默认值为 `1000`。
+ `"maxFetchRecordsPerShard"`：（可选）用于读取。每个微批次将从 Kinesis 数据流中的每个分片获取的最大记录数。注意：如果流式传输作业已经从 Kinesis 读取了额外的记录（在同一个 get-records 调用中），则客户端可以超过此限制。如果 `maxFetchRecordsPerShard` 需要严格，则必须是 `maxRecordPerRead` 的整数倍。默认值为 `100000`。
+ `"maxRecordPerRead"`：（可选）用于读取。每项 `getRecords` 操作中要从 Kinesis 数据流获取的最大记录数。默认值为 `10000`。
+ `"addIdleTimeBetweenReads"`：（可选）用于读取。在两项连续 `getRecords` 操作之间添加时间延迟。默认值为 `"False"`。此选项仅适用于 Glue 版本 2.0 及更高版本。
+ `"idleTimeBetweenReadsInMs"`：（可选）用于读取。两项连续 `getRecords` 操作之间的最短时间延迟，以毫秒为单位。默认值为 `1000`。此选项仅适用于 Glue 版本 2.0 及更高版本。
+ `"describeShardInterval"`：（可选）用于读取。两个 `ListShards` API 调用之间的最短时间间隔，供您的脚本考虑重新分区。有关更多信息，请参阅《Amazon Kinesis Data Streams 开发人员指南》中的[重新分区策略](https://docs.aws.amazon.com//streams/latest/dev/kinesis-using-sdk-java-resharding-strategies.html)**。默认值为 `1s`。
+ `"numRetries"`：（可选）用于读取。Kinesis Data Streams API 请求的最大重试次数。默认值为 `3`。
+ `"retryIntervalMs"`：（可选）用于读取。重试 Kinesis Data Streams API 调用之前的冷却时间（以毫秒为单位指定）。默认值为 `1000`。
+ `"maxRetryIntervalMs"`：（可选）用于读取。Kinesis Data Streams API 调用的两次重试之间的最长冷却时间（以毫秒为单位指定）。默认值为 `10000`。
+ `"avoidEmptyBatches"`：（可选）用于读取。在批处理开始之前检查 Kinesis 数据流中是否有未读数据，避免创建空白微批处理任务。默认值为 `"False"`。
+ `"schema"`：（当 inferSchema 设为 false 时为必填）用于读取。用于处理有效负载的架构。如果分类为 `avro`，则提供的架构必须采用 Avro 架构格式。如果分类不是 `avro`，则提供的架构必须采用 DDL 架构格式。

  以下是一些架构示例。

------
#### [ Example in DDL schema format ]

  ```
  `column1` INT, `column2` STRING , `column3` FLOAT
  ```

------
#### [ Example in Avro schema format ]

  ```
  {
    "type":"array",
    "items":
    {
      "type":"record",
      "name":"test",
      "fields":
      [
        {
          "name":"_id",
          "type":"string"
        },
        {
          "name":"index",
          "type":
          [
            "int",
            "string",
            "float"
          ]
        }
      ]
    }
  }
  ```

------
+ `"inferSchema"`：（可选）用于读取。默认值为‘false’。如果设置为“true”，则会在运行时检测到 `foreachbatch` 内的有效工作负载中的架构。
+ `"avroSchema"`：（已弃用）用于读取。用于指定 Avro 数据架构（使用 Avro 格式时）的参数。此参数现已被弃用。使用 `schema` 参数。
+ `"addRecordTimestamp"`：（可选）用于读取。当选项设置为 'true' 时，数据输出将包含一个名为 "\$1\$1src\$1timestamp" 的附加列，表示数据流收到相应记录的时间。默认值为‘false’。4.0 或更高 AWS Glue 版本支持此选项。
+ `"emitConsumerLagMetrics"`：（可选）用于读取。当选项设置为“true”时，对于每个批次，它将向 CloudWatch 发布数据流接收到的最早记录与该记录到达 AWS Glue 之间的时长指标。指标名称为 "glue.driver.streaming.maxConsumerLagInMs"。默认值为‘false’。4.0 或更高 AWS Glue 版本支持此选项。
+ `"fanoutConsumerARN"`：（可选）用于读取。`streamARN` 中指定的流的 Kinesis 流用户的 ARN。用于为您的 Kinesis 连接启用增强型扇出功能模式。有关使用增强型扇出功能的 Kinesis 流的更多信息，请参阅 [在 Kinesis 流作业中使用增强型扇出功能](aws-glue-programming-etl-connect-kinesis-efo.md)。
+ `"recordMaxBufferedTime"` –（可选）用于写入。默认值：1000（ms）。记录在等待写入时缓冲的最长时间。
+ `"aggregationEnabled"` –（可选）用于写入。默认值：真。指定是否应在将记录发送到 Kinesis 之前对其进行汇总。
+ `"aggregationMaxSize"` –（可选）用于写入。默认值：51200（字节）。如果记录超过了此限制，则它将绕过聚合器。注意：Kinesis 将记录大小限制为 50KB。如果您将其设置为 50KB 以上，Kinesis 将拒绝过大的记录。
+ `"aggregationMaxCount"` –（可选）用于写入。默认值：4294967295。要打包至汇总记录的最大项目数量。
+ `"producerRateLimit"` –（可选）用于写入。默认值：150（%）。限制从单个生产者（例如您的作业）发送的每个分片的吞吐量，以占后端限制的百分比表示。
+ `"collectionMaxCount"` –（可选）用于写入。默认值：500。要装入 PutRecords 请求的最大项目数量。
+ `"collectionMaxSize"` –（可选）用于写入。默认值：5242880（字节）。通过 PutRecords 请求发送的最大数据量。

# 在 Kinesis 流作业中使用增强型扇出功能
<a name="aws-glue-programming-etl-connect-kinesis-efo"></a>

使用增强型扇出功能的用户能够接收来自 Kinesis 流的记录，其专用吞吐量可能高于普通用户。这是通过优化用于向 Kinesis 用户（例如您的作业）提供数据的传输协议来完成的。有关 Kinesis 增强型扇出功能的更多信息，请参阅 [Kinesis 文档](https://docs.aws.amazon.com//streams/latest/dev/enhanced-consumers.html)。

在增强型扇出功能模式下，`maxRecordPerRead` 和 `idleTimeBetweenReadsInMs` 连接选项不再适用，因为使用增强型扇出功能时这些参数不可配置。重试的配置选项按所述执行。

使用以下步骤为您的流作业启用和禁用增强型扇出功能。应为每项将消耗流中数据的作业注册一个流用户。

**要在作业中启用增强型扇出功能使用，请执行以下操作：**

1. 使用 Kinesis API 为作业注册流用户。按照说明，使用 [Kinesis 文档](https://docs.aws.amazon.com//streams/latest/dev/building-enhanced-consumers-api)中的*使用 Kinesis Data Streams API 为用户注册增强型扇出功能*。只需要按照第一步进行操作，即调用 [RegisterStreamConsumer](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_RegisterStreamConsumer.html)。您的请求应返回 ARN *consumerARN*。

1. 在连接方法参数中将连接选项 `fanoutConsumerARN` 设置为 *consumerARN*。

1. 重新启动作业。

**要在作业中禁用增强型扇出功能使用，请执行以下操作：**

1. 从方法调用中移除 `fanoutConsumerARN` 连接选项。

1. 重新启动作业。

1. 按照 [Kinesis 文档](https://docs.aws.amazon.com/streams/latest/dev/building-enhanced-consumers-console.html)中的说明，*取消注册用户*。这些说明适用于控制台，但也可以通过 Kinesis API 来实现。有关通过 Kinesis API 取消注册流用户的更多信息，请查阅 Kinesis 文档中的 [DeregisterStreamConsumer](https://docs.aws.amazon.com//kinesis/latest/APIReference/API_DeregisterStreamConsumer.html)。

# Amazon S3 连接
<a name="aws-glue-programming-etl-connect-s3-home"></a>

您可以使用 AWS Glue for Spark 在 Amazon S3 中读取和写入文件。AWSGlue for Spark 支持许多开箱即用的存储在 Amazon S3 中的常见数据格式，包括 CSV、Avro、JSON、Orc 和 Parquet。有关支持的数据格式的更多信息，请参阅 [AWS Glue for Spark 中的输入和输出的数据格式选项](aws-glue-programming-etl-format.md)。每种数据格式可能支持不同的 AWS Glue 功能集。有关功能支持的细节，请查阅您的数据格式页面。此外，您可以读取和写入存储在 Hudi、Iceberg 和 Delta Lake 数据湖框架中的版本控制文件。有关数据湖框架的更多信息，请参阅 [在 AWS Glue ETL 任务中使用数据湖框架](aws-glue-programming-etl-datalake-native-frameworks.md)。

使用 AWS Glue，您可以在写入时将 Amazon S3 对象分成文件夹结构，然后使用简单的配置按分区检索以提高性能。您还可以设置配置，以便在转换数据时将小文件分组在一起以提高性能。您可以在 Amazon S3 中进行读写 `bzip2` 和 `gzip` 存档。

**Topics**
+ [

## 配置 S3 连接
](#aws-glue-programming-etl-connect-s3-configure)
+ [

## Amazon S3 连接选项参考
](#aws-glue-programming-etl-connect-s3)
+ [

## 已弃用的数据格式连接语法
](#aws-glue-programming-etl-connect-legacy-format)
+ [

# 排除 Amazon S3 存储类
](aws-glue-programming-etl-storage-classes.md)
+ [

# 管理 AWS Glue 中用于 ETL 输出的分区
](aws-glue-programming-etl-partitions.md)
+ [

# 以较大的组读取输入文件
](grouping-input-files.md)
+ [

# 适用于 Amazon S3 的 Amazon VPC 终端节点
](vpc-endpoints-s3.md)

## 配置 S3 连接
<a name="aws-glue-programming-etl-connect-s3-configure"></a>

要在 AWS Glue with Spark 作业中连接到 Amazon S3，需要具备一些先决条件：
+ AWS Glue 作业必须拥有对相关 Amazon S3 存储桶的 IAM 权限。

在某些情况下，您需要配置其他先决条件：
+ 配置跨账户访问时，需要对 Amazon S3 存储桶进行适当的访问控制。
+ 出于安全考虑，您可以选择通过 Amazon VPC 路由您的 Amazon S3 请求。此方法可能会带来带宽和可用性方面的难题。有关更多信息，请参阅 [适用于 Amazon S3 的 Amazon VPC 终端节点](vpc-endpoints-s3.md)。

## Amazon S3 连接选项参考
<a name="aws-glue-programming-etl-connect-s3"></a>

指定与 Amazon S3 的连接。

由于 Amazon S3 管理文件而不是表，因此除了指定本文档中提供的连接属性外，您还需要指定有关文件类型的额外配置。您可以通过数据格式选项来指定此信息。有关格式选项的更多信息，请参阅 [AWS Glue for Spark 中的输入和输出的数据格式选项](aws-glue-programming-etl-format.md)。您也可以通过与 AWS Glue Data Catalog 集成来指定此信息。

有关连接选项和格式选项之间区别的示例，请考虑 [create\$1dynamic\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法如何采用 `connection_type`、`connection_options`、`format` 和 `format_options`。本节专门讨论提供给 `connection_options` 的参数。

`"connectionType": "s3"` 可使用以下连接选项：
+ `"paths"`：（必需）要从中读取数据的 Amazon S3 路径的列表。
+ `"exclusions"`：（可选）包含要排除的 Unix 样式 glob 模式的 JSON 列表的字符串。例如，`"[\"**.pdf\"]"` 会排除所有 PDF 文件。有关 AWS Glue 支持的 glob 语法的更多信息，请参阅[包含和排除模式](https://docs.aws.amazon.com/glue/latest/dg/define-crawler.html#crawler-data-stores-exclude)。
+ `"compressionType"` 或 "`compression`"：（可选）指定数据压缩方式。使用适用于 Amazon S3 源的 `"compressionType"` 以及适用于 Amazon S3 目标的 `"compression"`。通常，如果数据有标准文件扩展名，则不需要指定。可能的值为 `"gzip"` 和 `"bzip2"`。特定格式可能支持其他压缩格式。有关功能支持的细节，请查阅数据格式页面。
+ `"groupFiles"`：（可选）当输入包含超过 50,000 个文件时，默认启用文件分组。当少于 50,000 个文件时，若要启用分组，请将此参数设置为 `"inPartition"`。当超过 50,000 个文件时，若要禁用分组，请将此参数设置为 `"none"`。
+ `"groupSize"`：（可选）目标组大小（以字节为单位）。默认值根据输入数据大小和群集大小进行计算。当少于 50,000 个输入文件时，`"groupFiles"` 必须设置为 `"inPartition"`，此选项才能生效。
+ `"recurse"`：（可选）如果设置为 true，则以递归方式读取指定路径下的所有子目录中的文件。
+ `"maxBand"`：（可选，高级）此选项控制 `s3` 列表可能保持一致的持续时间（以毫秒为单位）。当使用 `JobBookmarks` 来表明 Amazon S3 最终一致性时，将专门跟踪修改时间戳在最后 `maxBand` 毫秒内的文件。大多数用户不需要设置此选项。默认值为 900000 毫秒或 15 分钟。
+ `"maxFilesInBand"`：（可选，高级）此选项指定在最后 `maxBand` 秒内可保存的最大文件数量。如果超过此值，额外的文件将会跳过，且只能在下一次作业运行中处理。大多数用户不需要设置此选项。
+ `"isFailFast"`：（可选）此选项用于确定 AWS Glue ETL 任务是否导致读取器解析异常。如果设置为 `true`，并且 Spark 任务的四次重试无法正确解析数据，则任务会快速失败。
+ `"catalogPartitionPredicate"`：（可选）用于读取。SQL `WHERE` 子句的内容。从具有大量分区的 Data Catalog 表中读取时使用。从 Data Catalog 索引中检索匹配的分区。与 `push_down_predicate` 一起使用，[create\$1dynamic\$1frame\$1from\$1catalog](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_catalog) 方法（以及其他类似方法）上的一个选项。有关更多信息，请参阅 [使用目录分区谓词进行服务器端筛选](aws-glue-programming-etl-partitions.md#aws-glue-programming-etl-partitions-cat-predicates)。
+ `"partitionKeys"`：（可选）用于写入。列标签字符串数组。AWSGlue 将按照此配置的指定对您的数据进行分区。有关更多信息，请参阅 [写入分区](aws-glue-programming-etl-partitions.md#aws-glue-programming-etl-partitions-writing)。
+ `"excludeStorageClasses"`：（可选）用于读取。指定 Amazon S3 存储类的字符串数组。AWSGlue 将根据此配置排除 Amazon S3 对象。有关更多信息，请参阅 [排除 Amazon S3 存储类](aws-glue-programming-etl-storage-classes.md)。

## 已弃用的数据格式连接语法
<a name="aws-glue-programming-etl-connect-legacy-format"></a>

某些数据格式可以使用特定的连接类型语法进行访问。此语法已被弃用。我们建议您改用 [AWS Glue for Spark 中的输入和输出的数据格式选项](aws-glue-programming-etl-format.md) 中提供的 `s3` 连接类型和格式选项来指定格式。

### "connectionType": "orc"
<a name="aws-glue-programming-etl-connect-orc"></a>

指定与 Amazon S3 中以 [Apache Hive 优化的行列式（ORC）](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC)文件格式存储的文件的连接。

`"connectionType": "orc"` 可使用以下连接选项：
+ `paths`：（必需）要从中读取数据的 Amazon S3 路径的列表。
+ *（其他选项名称/值对）*：任何其他选项（包括格式化选项）将直接传递给 SparkSQL `DataSource`。

### "connectionType": "parquet"
<a name="aws-glue-programming-etl-connect-parquet"></a>

指定与 Amazon S3 中以 [Apache Parquet](https://parquet.apache.org/docs/) 文件格式存储的文件的连接。

`"connectionType": "parquet"` 可使用以下连接选项：
+ `paths`：（必需）要从中读取数据的 Amazon S3 路径的列表。
+ *（其他选项名称/值对）*：任何其他选项（包括格式化选项）将直接传递给 SparkSQL `DataSource`。

# 排除 Amazon S3 存储类
<a name="aws-glue-programming-etl-storage-classes"></a>

如果您要运行从 Amazon Simple Storage Service（Amazon S3）读取文件或分区的 AWS Glue ETL 任务，则可以排除某些 Amazon S3 存储类类型。

Amazon S3 中提供以下存储类：
+ `STANDARD` – 用于频繁访问数据的通用存储。
+ `INTELLIGENT_TIERING` – 用于具有未知或访问模式不断变化的数据。
+ `STANDARD_IA` 和 `ONEZONE_IA` – 用于长期存在但不常访问的数据。
+ `GLACIER`、`DEEP_ARCHIVE` 和 `REDUCED_REDUNDANCY` – 用于长期归档和数字化保存。

有关更多信息，请参阅《Amazon S3 开发人员指南》**中的 [Amazon S3 存储类](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html)。

本节中的示例向您展示了如何排除 `GLACIER` 和 `DEEP_ARCHIVE` 存储类。这些类允许您列出文件，但除非文件已还原，否则它们不会让您读取文件。（有关更多信息，请参阅《Amazon S3 开发人员指南》**中的[还原存档对象](https://docs.aws.amazon.com/AmazonS3/latest/dev/restoring-objects.html)。

通过使用存储类排除，您可以确保您的 AWS Glue 作业可以在具有跨这些存储类层的分区的表上工作。如果没有排除，则从这些层读取数据的作业将失败，并显示以下错误：AmazonS3Exception：操作对于此对象的存储类无效。

有多种不同的方法可供您在 AWS Glue 中筛选 Amazon S3 存储类。

**Topics**
+ [

## 创建动态帧时排除 Amazon S3 存储类
](#aws-glue-programming-etl-storage-classes-dynamic-frame)
+ [

## 在数据目录表上排除 Amazon S3 存储类
](#aws-glue-programming-etl-storage-classes-table)

## 创建动态帧时排除 Amazon S3 存储类
<a name="aws-glue-programming-etl-storage-classes-dynamic-frame"></a>

要在创建动态帧时排除 Amazon S3 存储类，请使用 `additionalOptions` 中的 `excludeStorageClasses`。 AWS Glue 会自动使用自己的 Amazon S3 `Lister` 实施列出和排除与指定存储类对应的文件。

以下 Python 和 Scala 示例显示了在创建动态帧时如何排除 `GLACIER` 和 `DEEP_ARCHIVE` 存储类。

Python 示例：

```
glueContext.create_dynamic_frame.from_catalog(
    database = "my_database",
    tableName = "my_table_name",
    redshift_tmp_dir = "",
    transformation_ctx = "my_transformation_context",
    additional_options = {
        "excludeStorageClasses" : ["GLACIER", "DEEP_ARCHIVE"]
    }
)
```

Scala 示例：

```
val* *df = glueContext.getCatalogSource(
    nameSpace, tableName, "", "my_transformation_context",  
    additionalOptions = JsonOptions(
        Map("excludeStorageClasses" -> List("GLACIER", "DEEP_ARCHIVE"))
    )
).getDynamicFrame()
```

## 在数据目录表上排除 Amazon S3 存储类
<a name="aws-glue-programming-etl-storage-classes-table"></a>

您可以将 AWS Glue ETL 任务使用的存储类排除指定为 AWS Glue 数据目录中的表参数。您可以使用 AWS Command Line Interface (AWS CLI) 或以编程方式使用 API 在 `CreateTable` 操作中包含此参数。有关更多信息，请参阅 [Table 结构](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-catalog-tables.html#aws-glue-api-catalog-tables-Table)和 [CreateTable](https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTable.html)。

您还可以在 AWS Glue 控制台上指定排除的存储类。

**排除 Amazon S3 存储类（控制台）**

1. 登录 AWS 管理控制台，然后打开 AWS Glue 控制台，网址为：[https://console.aws.amazon.com/glue/](https://console.aws.amazon.com/glue/)。

1. 在左侧的导航窗格中，选择 **Tables (表)**。

1. 选择列表中的表名称，然后选择 **Edit table (编辑表)**。

1. 在 **Table properties (表属性)** 中，添加 **excludeStorageClasses** 作为键，添加 **[\$1"GLACIER\$1",\$1"DEEP\$1ARCHIVE\$1"]** 作为值。

1. 选择**应用**。

# 管理 AWS Glue 中用于 ETL 输出的分区
<a name="aws-glue-programming-etl-partitions"></a>

分区是用于组织数据集以便高效查询数据集的重要技术。它根据一个或多个列的不同值用分层目录结构来组织数据。

例如，您可以决定按日期（包括年、月和日）对 Amazon Simple Storage Service（Amazon S3）中的应用程序日志分区。然后，与某一天的数据相对应的文件将放置在前缀下，例如 `s3://my_bucket/logs/year=2018/month=01/day=23/`。Amazon Athena、Amazon Redshift Spectrum 和 AWS Glue 等系统可以使用这些分区按分区值筛选数据，而无需读取 Amazon S3 中的所有底层数据。

爬网程序不仅推断文件类型和架构，它们还会在填充 AWS Glue 数据目录时自动标识数据集的分区结构。生成的分区列可用于在 AWS Glue ETL 任务或 Amazon Athena 之类的查询引擎中进行查询。

对表进行网络爬取后，您可以查看爬网程序创建的分区。在 AWS Glue 控制台的左侧导航窗格中，选择 **Tables (表)**。选择爬网程序创建的表，然后选择 **View Partitions (查看分区)**。

对于采用 `key=val` 样式的 Apache Hive 风格分区路径，爬网程序会使用键名自动填充列名称。否则，它使用默认名称，如 `partition_0`、`partition_1` 等。您可以在控制台上更改默认名称。为此，请导航至该表格。检查**索引**选项卡下是否存在索引。如果是这样的话，您需要删除它们才能继续（之后您可以使用新的列名重新创建它们）。然后，选择**编辑架构**，并在那里修改分区列的名称。

然后，在您的 ETL 脚本中，便可以筛选分区列。因为分区信息存储于数据目录，所以使用 `from_catalog` API 调用包含 `DynamicFrame` 中的分区列。例如，使用 `create_dynamic_frame.from_catalog` 而不是 `create_dynamic_frame.from_options`。

分区是一种可减少数据扫描量的优化技术。要详细了解确定何时适合使用这种技术的过程，请参阅《AWS 规范性指南》中“优化 AWS Glue for Apache Spark 作业性能的最佳实践”**指南中的 [减少数据扫描量](https://docs.aws.amazon.com/prescriptive-guidance/latest/tuning-aws-glue-for-apache-spark/reduce-data-scan.html)。

## 使用下推谓词进行预筛选
<a name="aws-glue-programming-etl-partitions-pushdowns"></a>

在许多情况下，您可以使用下推谓词来筛选分区，而不必列出并读取数据集中的所有文件。您可以直接对数据目录中的分区元数据应用筛选，而不是读取整个数据集，然后在 DynamicFrame 中筛选。这样，只需将您实际需要的内容列出和读取到 DynamicFrame 中即可。

例如，在 Python 中，您可以写入以下内容。

```
glue_context.create_dynamic_frame.from_catalog(
    database = "my_S3_data_set",
    table_name = "catalog_data_table",
    push_down_predicate = my_partition_predicate)
```

这会创建一个 DynamicFrame，它仅在数据目录中加载满足谓词表达式的分区。根据您要加载的数据子集的规模，这样可以节省大量处理时间。

谓词表达式可以是 Spark SQL 支持的任何布尔表达式。您可以在 Spark SQL 查询的 `WHERE` 子句中放置的任何内容都可以使用。例如，谓词表达式 `pushDownPredicate = "(year=='2017' and month=='04')"` 仅加载数据目录中 `year` 等于 2017 并且 `month` 等于 04 的分区。有关更多信息，请参阅 [Apache Spark SQL 文档](https://spark.apache.org/docs/2.1.1/sql-programming-guide.html)，尤其是 [Scala SQL 函数参考](https://spark.apache.org/docs/2.1.1/api/scala/index.html#org.apache.spark.sql.functions$)。

## 使用目录分区谓词进行服务器端筛选
<a name="aws-glue-programming-etl-partitions-cat-predicates"></a>

`push_down_predicate` 选项将在列出目录中的所有分区之后以及列出 Amazon S3 中针对这些分区的文件之前应用。如果您有大量表分区，则目录分区列表仍然会产生额外的时间开销。为解决这一开销，您可以结合使用服务器端分区修剪和 `catalogPartitionPredicate` 选项，该选项使用 AWS Glue 数据目录中的[分区索引](https://docs.aws.amazon.com/glue/latest/dg/partition-indexes.html)。当您在一个表中有数百万个分区时，这样可以提高分区筛选速度。如果您的 `catalogPartitionPredicate` 需要目录分区索引尚不支持的谓词语法，您可以结合使用 `push_down_predicate` 与 `additional_options` 中的 `catalogPartitionPredicate`。

Python：

```
dynamic_frame = glueContext.create_dynamic_frame.from_catalog(
    database=dbname, 
    table_name=tablename,
    transformation_ctx="datasource0",
    push_down_predicate="day>=10 and customer_id like '10%'",
    additional_options={"catalogPartitionPredicate":"year='2021' and month='06'"}
)
```

Scala：

```
val dynamicFrame = glueContext.getCatalogSource(
    database = dbname,
    tableName = tablename, 
    transformationContext = "datasource0",
    pushDownPredicate="day>=10 and customer_id like '10%'",
    additionalOptions = JsonOptions("""{
        "catalogPartitionPredicate": "year='2021' and month='06'"}""")
    ).getDynamicFrame()
```

**注意**  
`push_down_predicate` 和 `catalogPartitionPredicate` 使用不同的语法。前者使用 Spark SQL 标准语法，后者使用 JSQL 解析器。

## 写入分区
<a name="aws-glue-programming-etl-partitions-writing"></a>

默认情况下，DynamicFrame 在写入时不分区。所有输出文件都写入指定输出路径的顶级。直到最近，将 DynamicFrame 写入分区的唯一途径是在写入之前将其转换为 Spark SQL DataFrame。

但是，DynamicFrames 现在支持您在创建接收器时使用 `partitionKeys` 选项通过密钥序列进行本机分区。例如，以下 Python 代码将数据集以 Parquet 格式写出到 Amazon S3 中，写入到类型字段分区的目录中。然后，您可以使用其他系统（如 Amazon Athena）处理这些分区。

```
glue_context.write_dynamic_frame.from_options(
    frame = projectedEvents,
    connection_type = "s3",    
    connection_options = {"path": "$outpath", "partitionKeys": ["type"]},
    format = "parquet")
```

# 以较大的组读取输入文件
<a name="grouping-input-files"></a>

您可以设置表的属性，以使 AWS Glue ETL 任务能够在从 Amazon S3 数据存储中读取文件时对文件分组。这些属性使每个 ETL 任务可将一组输入文件读取到单个内存分区中，当 Amazon S3 数据存储中存在大量小型文件时，此功能特别有用。当您设置某些属性时，您会指示 AWS Glue 对 Amazon S3 数据分区中的文件分组并设置要读取的组的大小。您还可以在从 Amazon S3 数据存储中读取时用 `create_dynamic_frame.from_options` 方法设置这些选项。

要对表启用文件分组，可在表结构的参数字段中设置键值对。使用 JSON 表示法为表的参数字段设置值。有关编辑表属性的更多信息，请参阅 [查看和管理表详细信息](tables-described.md#console-tables-details)。

您可以使用此方法对数据目录中使用 Amazon S3 数据存储的表启用分组。

**groupFiles**  
将 **groupFiles** 设置为 `inPartition`，以在 Amazon S3 数据分区中启用文件分组。如果输入文件数多于 50000 个，AWS Glue 会自动启用分组，如以下示例中所示。  

```
  'groupFiles': 'inPartition'
```

**groupSize**  
将 **groupSize** 设置为组的目标大小 (以字节为单位)。**groupSize** 属性为可选属性，如果未提供，AWS Glue 将计算一个大小以使用集群中的所有 CPU 内核，同时仍会减少 ETL 任务和内存分区总数。  
例如，以下内容将组大小设置为 1 MB。  

```
  'groupSize': '1048576'
```
请注意，应使用计算的结果设置 `groupsize`。例如，1024 \$1 1024 = 1048576。

**recurse**  
将**递归**设置为 `True`，这样在将 `paths` 指定为路径数组时，会以递归方式读取所有子目录中的文件。如果 `paths` 是 Amazon S3 中的一组对象密钥，或者输入格式为 parquet/orc，您不需要将其设置为 **recurse**，如以下示例所示。  

```
  'recurse':True
```

如果您使用 `create_dynamic_frame.from_options` 方法直接从 Amazon S3 中读取，请添加这些连接选项。例如，下面尝试将文件分组到 1 MB 组中。

```
df = glueContext.create_dynamic_frame.from_options("s3", {'paths': ["s3://s3path/"], 'recurse':True, 'groupFiles': 'inPartition', 'groupSize': '1048576'}, format="json")
```

**注意**  
从以下数据格式创建的 DynamicFrames 支持 `groupFiles`：csv、ion、grokLog、json 和 xml。avro、parquet 和 orc 不支持此选项。

# 适用于 Amazon S3 的 Amazon VPC 终端节点
<a name="vpc-endpoints-s3"></a>

出于安全原因，许多AWS客户在 Amazon Virtual Private Cloud 环境（Amazon VPC）中运行其应用程序。利用 Amazon VPC，您可以在 Virtual Private Cloud 中启动 Amazon EC2 实例，Virtual Private Cloud 在逻辑上与其他网络（包括公共互联网）隔离。利用 Amazon VPC，您可以控制该网络的 IP 地址范围、子网、路由表、网络网关和安全设置。

**注意**  
如果您的AWS账户是在 2013 年 12 月 4 日之后创建的，则您在每个AWS区域都已经有一个默认 VPC。您无需任何额外配置即能立即开始使用您的默认 VPC。  
详情请参阅《Amazon VPC 用户指南》中的[您的默认 VPC 和子网](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html)。

许多客户对跨公共 Internet 发送和接收数据存在合理的私密性和安全性担心。客户可以利用 virtual private network (VPN)，通过其企业网络基础设施路由所有 Amazon S3 网络流量，从而消除这些担心。不过，此方法可能会带来带宽和可用性方面的难题。

Amazon S3 的 VPC 终端节点可以克服这些难题。Amazon S3 的 VPC 终端节点使 AWS Glue 可以使用私有 IP 地址访问 Amazon S3，而无需接触公共互联网。AWS Glue 不需要公有 IP 地址，因此您的 VPC 中不需要有互联网网关、NAT 设备或虚拟私有网关。您使用终端节点策略控制对 Amazon S3 的访问。您的 VPC 和AWS服务之间的流量不会脱离 Amazon 网络。

在为 Amazon S3 创建 VPC 终端节点时，发送到区域（如 *s3.us-west-2.amazonaws.com*）内的 Amazon S3 终端节点的任何请求都被路由到亚马逊网络中的私有 Amazon S3 终端节点。您不需要修改正在 VPC 中的 Amazon EC2 实例上运行的应用程序 – 终端节点名称保持不变，但到 Amazon S3 的路由会完全保留在亚马逊网络中，不会访问公共互联网。

有关 VPC 终端节点的更多信息，请参阅《Amazon VPC 用户指南》中的 [VPC 终端节点](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints.html)。

下图说明 AWS Glue 如何使用 VPC 终端节点访问 Amazon S3。

![\[显示 VPC 连接到 Amazon S3 的网络流量。\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/PopulateCatalog-vpc-endpoint.png)


**设置 Amazon S3 访问权限**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon VPC 控制台：[https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/)。

1. 在左侧导航窗格中，选择**终端节点**。

1. 选择 **Create Endpoint (创建终端节点)**，然后按照步骤创建网关类型的 Amazon S3 VPC 终端节点。

# Amazon DocumentDB 连接
<a name="aws-glue-programming-etl-connect-documentdb-home"></a>

您可以使用 AWS Glue for Spark 读取和写入 Amazon DocumentDB 中的表。您可以通过 AWS Glue 连接使用存储在 AWS Secrets Manager 中的凭证连接到 Amazon DocumentDB。

有关 Amazon DocumentDB 的更多信息，请参阅 [Amazon DocumentDB 文档](https://docs.aws.amazon.com/documentdb/latest/developerguide/what-is.html)。

**注意**  
使用 AWS Glue 连接器时，目前不支持 Amazon DocumentDB 弹性集群。有关弹性集群的更多信息，请参阅 [Using Amazon DocumentDB elastic clusters](https://docs.aws.amazon.com/documentdb/latest/developerguide/docdb-using-elastic-clusters.html)。

## 读取和写入 Amazon DocumentDB 集合
<a name="aws-glue-programming-etl-connect-documentdb-read-write"></a>

**注意**  
当您创建连接到 Amazon DocumentDB 的 ETL 任务时，对于 `Connections` 任务属性，您必须指定一个连接对象，用于指定在其中运行 Amazon DocumentDB 的 Virtual Private Cloud（VPC）。对于该连接对象，连接类型必须为 `JDBC`，且 `JDBC URL` 必须为 `mongo://<DocumentDB_host>:27017`。

**注意**  
这些代码示例是为 AWS Glue 3.0 开发的。要迁移到 AWS Glue 4.0，请参阅 [MongoDB](migrating-version-40.md#migrating-version-40-connector-driver-migration-mongodb)。`uri` 参数已更改。

**注意**  
使用 Amazon DocumentDB 时，在某些情况下必须将 `retryWrites` 设置为 false，例如编写的文档指定 `_id` 时。有关更多信息，请参阅 Amazon DocumentDB 文档中的 [与 MongoDB 之间的功能差异](https://docs.aws.amazon.com/documentdb/latest/developerguide/functional-differences.html#functional-differences.retryable-writes)。

以下 Python 脚本展示了如何使用连接类型和连接选项来读写 Amazon DocumentDB。

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext, SparkConf
from awsglue.context import GlueContext
from awsglue.job import Job
import time

## @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

job = Job(glueContext)
job.init(args['JOB_NAME'], args)

output_path = "s3://some_bucket/output/" + str(time.time()) + "/"
documentdb_uri = "mongodb://<mongo-instanced-ip-address>:27017"
documentdb_write_uri = "mongodb://<mongo-instanced-ip-address>:27017"

read_docdb_options = {
    "uri": documentdb_uri,
    "database": "test",
    "collection": "coll",
    "username": "username",
    "password": "1234567890",
    "ssl": "true",
    "ssl.domain_match": "false",
    "partitioner": "MongoSamplePartitioner",
    "partitionerOptions.partitionSizeMB": "10",
    "partitionerOptions.partitionKey": "_id"
}

write_documentdb_options = {
    "retryWrites": "false",
    "uri": documentdb_write_uri,
    "database": "test",
    "collection": "coll",
    "username": "username",
    "password": "pwd"
}

# Get DynamicFrame from  DocumentDB
dynamic_frame2 = glueContext.create_dynamic_frame.from_options(connection_type="documentdb",
                                                               connection_options=read_docdb_options)

# Write DynamicFrame to MongoDB and DocumentDB
glueContext.write_dynamic_frame.from_options(dynamic_frame2, connection_type="documentdb",
                                             connection_options=write_documentdb_options)

job.commit()
```

以下 Scala 脚本展示了如何使用连接类型和连接选项来读写 Amazon DocumentDB。

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._

object GlueApp {
  val DOC_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  val DOC_WRITE_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  lazy val documentDBJsonOption = jsonOptions(DOC_URI)
  lazy val writeDocumentDBJsonOption = jsonOptions(DOC_WRITE_URI)
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    // Get DynamicFrame from DocumentDB
    val resultFrame2: DynamicFrame = glueContext.getSource("documentdb", documentDBJsonOption).getDynamicFrame()

    // Write DynamicFrame to DocumentDB
    glueContext.getSink("documentdb", writeJsonOption).writeDynamicFrame(resultFrame2)

    Job.commit()
  }

  private def jsonOptions(uri: String): JsonOptions = {
    new JsonOptions(
      s"""{"uri": "${uri}",
         |"database":"test",
         |"collection":"coll",
         |"username": "username",
         |"password": "pwd",
         |"ssl":"true",
         |"ssl.domain_match":"false",
         |"partitioner": "MongoSamplePartitioner",
         |"partitionerOptions.partitionSizeMB": "10",
         |"partitionerOptions.partitionKey": "_id"}""".stripMargin)
  }
}
```

## Amazon DocumentDB 连接选项参考
<a name="aws-glue-programming-etl-connect-documentdb"></a>

指定与 Amazon DocumentDB (with MongoDB compatibility) 的连接。

源连接和接收器连接的连接选项不同。

### "connectionType": "documentdb" as Source
<a name="etl-connect-documentdb-as-source"></a>

将 `"connectionType": "documentdb"` 用作源时可使用以下连接选项：
+ `"uri"`：（必需）要从中读取数据的 Amazon DocumentDB 主机，格式为 `mongodb://<host>:<port>`。
+ `"database"`：（必需）要从中读取数据的 Amazon DocumentDB 数据库。
+ `"collection"`：（必需）要从中读取数据的 Amazon DocumentDB 连接。
+ `"username"`：（必需）Amazon DocumentDB 用户名。
+ `"password"`：（必需）Amazon DocumentDB 密码。
+ `"ssl"`：（如果使用 SSL，则必需）如果您的连接使用 SSL，则必须包含此选项且值为 `"true"`。
+ `"ssl.domain_match"`：（如果使用 SSL，则必需）如果您的连接使用 SSL，则必须包含此选项且值为 `"false"`。
+ `"batchSize"`：（可选）每个批处理返回的文档数量，在内部批处理的游标中使用。
+ `"partitioner"`：（可选）从 Amazon DocumentDB 中读取输入数据的分区器的类名称。该连接器提供以下分区器：
  + `MongoDefaultPartitioner`（默认）（AWS Glue 4.0 不支持）
  + `MongoSamplePartitioner`（AWS Glue 4.0 不支持）
  + `MongoShardedPartitioner`
  + `MongoSplitVectorPartitioner`
  + `MongoPaginateByCountPartitioner`
  + `MongoPaginateBySizePartitioner`（AWS Glue 4.0 不支持）
+ `"partitionerOptions"`：（可选）指定分区器的选项。各个分区器支持的选项如下：
  + `MongoSamplePartitioner`: `partitionKey`, `partitionSizeMB`, `samplesPerPartition`
  + `MongoShardedPartitioner`: `shardkey`
  + `MongoSplitVectorPartitioner`：`partitionKey`、partitionSizeMB
  + `MongoPaginateByCountPartitioner`: `partitionKey`, `numberOfPartitions`
  + `MongoPaginateBySizePartitioner`：`partitionKey`、partitionSizeMB

  有关这些选项的更多信息，请参阅 MongoDB 文档中的[分区器配置](https://docs.mongodb.com/spark-connector/master/configuration/#partitioner-conf)。

### "connectionType": "documentdb" as Sink
<a name="etl-connect-documentdb-as-sink"></a>

将 `"connectionType": "documentdb"` 用作连接器时可使用以下连接选项：
+ `"uri"`：（必需）要在其中写入数据的 Amazon DocumentDB 主机，格式为 `mongodb://<host>:<port>`。
+ `"database"`：（必需）要在其中写入数据的 Amazon DocumentDB 数据库。
+ `"collection"`：（必需）要在其中写入数据的 Amazon DocumentDB 连接。
+ `"username"`：（必需）Amazon DocumentDB 用户名。
+ `"password"`：（必需）Amazon DocumentDB 密码。
+ `"extendedBsonTypes"`：（可选）如果为 `true`，则在 Amazon DocumentDB 中写入数据时会启用扩展 BSON 类型。默认值为 `true`。
+ `"replaceDocument"`：（可选）如果为 `true`，则在保存包含 `_id` 字段的数据集时会替换整个文档。如果为 `false`，则只会更新文档中与数据集中的字段匹配的字段。默认值为 `true`。
+ `"maxBatchSize"`：（可选）保存数据时的批量操作的最大批次大小。默认值为 512。
+ `"retryWrites"`：（可选）：如果 AWS Glue 遇到网络错误，则会自动重试某些写入操作一次。

# OpenSearch Service 连接
<a name="aws-glue-programming-etl-connect-opensearch-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 来读取和写入 OpenSearch Service 中的表。您可以使用 OpenSearch 查询来定义要从 OpenSearch Service 中读取的内容。您可以使用存储在 AWS Secrets Manager 中的 HTTP 基本身份验证凭证，并通过 AWS Glue 连接来连接到 OpenSearch Service。此功能与 OpenSearch Service 无服务器不兼容。

有关 Amazon OpenSearch Service 的更多信息，请参阅 [Amazon OpenSearch Service 文档](https://docs.aws.amazon.com/opensearch-service/)。

## 配置 OpenSearch Service 连接
<a name="aws-glue-programming-etl-connect-opensearch-configure"></a>

要从 AWS Glue 连接到 OpenSearch Service，您需要创建 OpenSearch Service 凭证并将其存储在 AWS Secrets Manager 密钥中，然后将该密钥关联到某个 OpenSearch Service AWS Glue 连接。

**先决条件** 
+ 确定您要从中读取的域端点 *aosEndpoint* 和端口 *aosPort*，或者按照 Amazon OpenSearch Service 文档中的说明创建资源。有关更多信息，请参阅《Amazon OpenSearch Service 开发人员指南》中的 [Creating and managing Amazon OpenSearch Service domains](https://docs.aws.amazon.com//opensearch-service/latest/developerguide/createupdatedomains.html)。

  Amazon OpenSearch Service 域端点的默认格式为 https://search-*domainName*-*unstructuredIdContent*.*region*.es.amazonaws.com。有关如何确定域端点的更多信息，请参阅《Amazon OpenSearch Service 开发人员指南》中的 [Creating and managing Amazon OpenSearch Service domains](https://docs.aws.amazon.com//opensearch-service/latest/developerguide/createupdatedomains.html)。

  确定或生成域的 HTTP 基本身份验证凭证（*aosUser* 和 *aosPassword*）。

**配置 OpenSearch Service 连接：**

1. 在 AWS Secrets Manager 中，使用您的 OpenSearch Service 凭证创建一个密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `USERNAME` 和值 *aosUser* 创建一个键值对。
   + 在选择**键/值对**时，请使用键 `PASSWORD` 和值 *aosPassword* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名为 *connectionName*，以供未来在 AWS Glue 中使用。
   + 选择**连接类型**时，请选择 OpenSearch Service。
   + 选择域端点时，请提供 *aosEndpoint*。
   + 选择端口时，请提供 *aosPort*。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

创建 AWS Glue OpenSearch Service 连接后，您需要完成以下操作，然后才能运行 AWS Glue 作业：
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 读取 OpenSearch Service 索引
<a name="aws-glue-programming-etl-connect-opensearch-read"></a>

**先决条件** 
+ 您要读取的 OpenSearch Service 索引 *aosIndex*。
+ 为了提供身份验证和网络位置信息而配置的 AWS Glue OpenSearch Service 连接。要获得此信息，请完成前面“配置 OpenSearch Service 连接”**中的步骤。您需要 AWS Glue 连接的名称 *connectionName*。

此示例将从 Amazon OpenSearch Service 读取索引。您需要提供 `pushdown` 参数。

例如：

```
opensearch_read = glueContext.create_dynamic_frame.from_options(
    connection_type="opensearch",
    connection_options={
        "connectionName": "connectionName",
        "opensearch.resource": "aosIndex",
        "pushdown": "true",
    }
)
```

您还可以提供查询字符串来筛选返回到 DynamicFrame 的结果。您将需要配置 `opensearch.query`。

`opensearch.query` 可以为 URL 查询参数字符串 *queryString*，也可以为查询 DSL JSON 对象 *queryObject*。有关查询 DSL 的更多信息，请参阅 OpenSearch 文档中的 [Query DSL](https://opensearch.org/docs/latest/query-dsl/index/)。要提供 URL 查询参数字符串，请在查询前面加上 `?q=`，这与完全限定 URL 中一样。要提供查询 DSL 对象，请首先对 JSON 对象进行字符串转义，然后再提供该对象。

例如：

```
            queryObject = "{ "query": { "multi_match": { "query": "Sample", "fields": [ "sample" ] } } }"
            queryString = "?q=queryString"
            
            opensearch_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="opensearch",
    connection_options={
        "connectionName": "connectionName",
        "opensearch.resource": "aosIndex",
        "opensearch.query": queryString,
        "pushdown": "true",
    }
)
```

有关如何构建不符合特定语法的查询的更多信息，请参阅 OpenSearch 文档中的 [Query string syntax](https://opensearch.org/docs/latest/query-dsl/full-text/query-string/#query-string-syntax)。

从包含数组类型数据的 OpenSearch 集合中读取时，必须使用 `opensearch.read.field.as.array.include` 参数在方法调用中指定哪些字段是数组类型。

例如，在阅读以下文档时，您会遇到 `genre` 和 `actor` 数组字段：

```
{
    "_index": "movies",
    "_id": "2",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "director": "Frankenheimer, John",
        "genre": [
            "Drama",
            "Mystery",
            "Thriller",
            "Crime"
        ],
        "year": 1962,
        "actor": [
            "Lansbury, Angela",
            "Sinatra, Frank",
            "Leigh, Janet",
            "Harvey, Laurence",
            "Silva, Henry",
            "Frees, Paul",
            "Gregory, James",
            "Bissell, Whit",
            "McGiver, John",
            "Parrish, Leslie",
            "Edwards, James",
            "Flowers, Bess",
            "Dhiegh, Khigh",
            "Payne, Julie",
            "Kleeb, Helen",
            "Gray, Joe",
            "Nalder, Reggie",
            "Stevens, Bert",
            "Masters, Michael",
            "Lowell, Tom"
        ],
        "title": "The Manchurian Candidate"
    }
}
```

在这种情况下，您将在方法调用中包含这些字段名称。例如：

```
"opensearch.read.field.as.array.include": "genre,actor"
```

如果您的数组字段嵌套在文档结构内部，请使用点表示法引用它：`"genre,actor,foo.bar.baz"`。这将通过包含嵌入式文档 `bar` 的嵌入式文档 `foo` 指定源文档中包含的数组 `baz`。

## 写入 OpenSearch Service 表
<a name="aws-glue-programming-etl-connect-opensearch-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 OpenSearch Service。如果索引中已经含有信息，AWS Glue 会将来自 DynamicFrame 的数据附加到现有信息之后。您需要提供 `pushdown` 参数。

**先决条件** 
+ 您要写入的 OpenSearch Service 表。您将需要该表的标识信息。我们称之为 *tableName*。
+ 为了提供身份验证和网络位置信息而配置的 AWS Glue OpenSearch Service 连接。要获得此信息，请完成前面“配置 OpenSearch Service 连接”**中的步骤。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="opensearch",
    connection_options={
      "connectionName": "connectionName",
      "opensearch.resource": "aosIndex",
    },
)
```

## OpenSearch Service 连接选项参考
<a name="aws-glue-programming-etl-connect-opensearch-reference"></a>
+ `connectionName` – 必需。用于读/写。为了向您的连接方法提供身份验证和网络位置信息而配置的 AWS Glue OpenSearch Service 连接的名称。
+ `opensearch.resource` – 必需。用于读/写。有效值：OpenSearch 索引名。您的连接方法将与之交互的索引的名称。
+ `opensearch.query` – 用于读取。有效值：字符串转义后的 JSON，如果此字符串以 `?` 开头，则为 URL 的搜索部分。用于在读取时筛选检索范围的 OpenSearch 查询。有关此参数用法的更多信息，请参阅上一节“[读取 OpenSearch Service 索引](#aws-glue-programming-etl-connect-opensearch-read)”。
+ `pushdown` – 对于下列情况为必填项。用于读取。有效值：布尔值。指示 Spark 将读取查询传递给 OpenSearch，以便数据库仅返回相关文档。
+ `opensearch.read.field.as.array.include` – 如果读取数组类型数据，则为必填项。用于读取。有效值：以逗号分隔的字段名称列表。指定要从 OpenSearch 文档中作为数组读取的字段。有关此参数用法的更多信息，请参阅上一节“[读取 OpenSearch Service 索引](#aws-glue-programming-etl-connect-opensearch-read)”。

# Redshift 连接
<a name="aws-glue-programming-etl-connect-redshift-home"></a>

您可以使用 AWS Glue for Spark 读取和写入 Amazon Redshift 数据库中的表。连接到 Amazon Redshift 数据库时，AWS Glue 使用 Amazon Redshift SQL `COPY` 和 `UNLOAD` 命令并通过 Amazon S3 移动数据以实现最大吞吐量。在 AWS Glue 4.0 及更高版本中，您可以使用[适用于 Apache Spark 的 Amazon Redshift 集成](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)进行读写，除了通过先前版本连接时可用的优化和功能外，还具有特定于 Amazon Redshift 的优化和功能。

了解 AWS Glue 如何让 Amazon Redshift 用户比以往任何时候都更轻松地迁移到 AWS Glue 进行无服务器数据集成和 ETL。

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


## 配置 Redshift 连接
<a name="aws-glue-programming-etl-connect-redshift-configure"></a>

要在 AWS Glue 中使用 Amazon Redshift 集群，需要具备一些先决条件：
+ 读取和写入数据库时用于临时存储的 Amazon S3 目录。
+ Amazon VPC，允许在 Amazon Redshift 集群、AWS Glue 作业和 Amazon S3 目录之间进行通信。
+ 对 AWS Glue 作业和 Amazon Redshift 集群具有相应的 IAM 权限。

### 配置 IAM 角色
<a name="aws-glue-programming-etl-redshift-config-iam"></a>

**为 Amazon Redshift 集群设置角色**  
您的 Amazon Redshift 集群需要能够读取和写入 Amazon S3，才能与 AWS Glue 作业集成。为此，您可以将 IAM 角色与要连接的新 Amazon Redshift 集群关联。您的角色应具有允许读取和写入 Amazon S3 临时目录的策略。您的角色应该有信任关系，允许 `redshift.amazonaws.com` 服务连接到 `AssumeRole`。

**将 IAM 角色与 Amazon Redshift 关联**

1. **先决条件：**用于临时存储文件的 Amazon S3 存储桶或目录。

1. 确定您的 Amazon Redshift 集群需要哪些 Amazon S3 权限。在将数据移入和移出 Amazon Redshift 集群时，AWS Glue 任务会对 Amazon Redshift 发出 COPY 和 UNLOAD 语句。如果您的作业修改了 Amazon Redshift 中的表，AWS Glue 还会发出 CREATE LIBRARY 语句。有关 Amazon Redshift 执行这些语句所需的特定 Amazon S3 权限的信息，请参阅 Amazon Redshift 文档：[Amazon Redshift: Permissions to access other AWS Resources](https://docs.aws.amazon.com/redshift/latest/dg/copy-usage_notes-access-permissions.html)。

1. 在 IAM 控制台中，创建具有必要权限的 IAM policy。有关创建策略的更多信息，请参阅 [Creating IAM policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html)。

1. 在 IAM 控制台中，创建角色和信任关系，允许 Amazon Redshift 担任该角色。按照 IAM 文档[为 AWS 服务（控制台）创建角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html#roles-creatingrole-service-console)中的说明操作
   + 当系统要求选择 AWS 服务用例时，选择“Redshift - 可自定义”。
   + 当系统要求附加策略时，请选择您之前定义的策略。
**注意**  
有关为 Amazon Redshift 配置角色的更多信息，请参阅 Amazon Redshift 文档中的 [Authorizing Amazon Redshift to access other AWS services on your behalf](https://docs.aws.amazon.com/redshift/latest/mgmt/authorizing-redshift-service.html)。

1. 在 Amazon Redshift 控制台中，将角色与您的 Amazon Redshift 集群关联。按照 [Amazon Redshift 文档](https://docs.aws.amazon.com/redshift/latest/mgmt/copy-unload-iam-role.html)中的说明操作。

   在 Amazon Redshift 控制台中选择突出显示的选项，配置此设置：  
![\[在 Amazon Redshift 控制台中何处管理 IAM 权限的示例。\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/RS-role-config.png)

**注意**  
 默认情况下，AWS Glue 作业会传入使用您指定的角色创建的 Amazon Redshift 临时凭证来运行作业。我们建议不使用这些凭证。出于安全考虑，这些凭证将在 1 小时后过期。

**为 AWS Glue 作业设置角色**  
AWS Glue 作业需要角色才能访问 Amazon S3 存储桶。您不需要 Amazon Redshift 集群的 IAM 权限，您的访问权限由 Amazon VPC 中的连接和您的数据库凭证控制。

### 设置 Amazon VPC
<a name="aws-glue-programming-etl-redshift-config-vpc"></a>

**设置 Amazon Redshift 数据存储访问权限**

1. 登录到 AWS 管理控制台并打开 Amazon Redshift 控制台，网址：[https://console.aws.amazon.com/redshiftv2/](https://console.aws.amazon.com/redshiftv2/)。

1. 在左侧导航窗格中，选择**集群**。

1. 选择要从 AWS Glue 访问的集群名称。

1. 在 **Cluster Properties (集群属性)** 部分，从 **VPC security groups (VPC 安全组)** 中选择一个安全组以允许 AWS Glue 使用。记录下所选的安全组名称以供将来参考。选择安全组将打开 Amazon EC2 控制台 **Security Groups (安全组)** 列表。

1. 选择要修改的安全组并导航到**入站**选项卡。

1. 添加一个自引用规则，以允许 AWS Glue 组件进行通信。具体来讲，添加或确认有一条**类型**为 `All TCP` 的规则，**协议**为 `TCP`，**端口范围**包括所有端口，其**源**具有与**组 ID**相同的安全组名。

   入站规则类似如下：  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/aws-glue-programming-etl-connect-redshift-home.html)

   例如：  
![\[自引用入站规则的示例。\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/SetupSecurityGroup-Start.png)

1. 同时也为出站流量添加一条规则。打开到所有端口的出站流量，例如：  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/aws-glue-programming-etl-connect-redshift-home.html)

   或创建一条 **Type (类型)** 为 `All TCP`、**Protocol (协议)** 为 `TCP`、**Port Range (端口范围)** 包括所有端口及其 **Destination (目标)** 具有与 **Group ID (组 ID)** 相同的安全组名称的自引用规则。如果使用 Amazon S3 VPC 终端节点，还可以添加 HTTPS 规则以访问 Amazon S3。安全组规则中必须提供 *s3-prefix-list-id* 以允许从该 VPC 到 Amazon S3 VPC 终端节点的流量。

   例如：  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/aws-glue-programming-etl-connect-redshift-home.html)

### 设置 AWS Glue
<a name="aws-glue-programming-etl-redshift-config-glue"></a>

您需要创建一个提供 Amazon VPC 连接信息的 AWS Glue Data Catalog 连接。

**在控制台中配置 Amazon Redshift Amazon VPC 与 AWS Glue 的连接**

1. 按照步骤创建 Data Catalog 连接：[添加 AWS Glue 连接](console-connections.md)。创建连接后，保留连接名称 *connectionName*，以供下一步使用。
   + 选择**连接类型**时，请选择 **Amazon Redshift**。
   + 选择 **Redshift 集群**时，按名称选择集群。
   + 为集群上的 Amazon Redshift 用户提供默认连接信息。
   + 您的 Amazon VPC 设置将自动配置。
**注意**  
通过 AWS SDK 创建 **Amazon Redshift** 连接时，您需要手动为 Amazon VPC 提供 `PhysicalConnectionRequirements`。

1. 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 示例：从 Amazon Redshift 表中读取
<a name="aws-glue-programming-etl-connect-redshift-read"></a>

 您可以从 Amazon Redshift 集群和 Amazon Redshift Serverless 环境中读取。

**先决条件：**您想读取的 Amazon Redshift 表。按照上一节 [配置 Redshift 连接](#aws-glue-programming-etl-connect-redshift-configure) 中的步骤进行操作，之后您应该拥有临时目录 *temp-s3-dir* 和 IAM 角色 *rs-role-name* 的 Amazon S3 URI（在账户 *role-account-id* 中）。

------
#### [ Using the Data Catalog ]

**其他先决条件：**您要从中读取 Amazon Redshift 表的 Data Catalog 数据库和表。有关 Data Catalog 的更多信息，请参阅 [AWS Glue 中的数据发现和编目](catalog-and-crawler.md)。*为 Amazon Redshift 表创建条目后，您将使用 *redshift-dc-database-name* 和 redshift-table-name* 来标识连接。

**配置：**在函数选项中，您将使用 `database` 和 `table_name` 参数标识数据目录表。您将使用 `redshift_tmp_dir` 标识 Amazon S3 临时目录。您还将使用 `additional_options` 参数中的 `aws_iam_role` 键提供 *rs-role-name*。

```
 glueContext.create_dynamic_frame.from_catalog(
    database = "redshift-dc-database-name", 
    table_name = "redshift-table-name", 
    redshift_tmp_dir = args["temp-s3-dir"], 
    additional_options = {"aws_iam_role": "arn:aws:iam::role-account-id:role/rs-role-name"})
```

------
#### [ Connecting directly ]

**其他先决条件：***您需要 Amazon Redshift 表的名称（redshift-table-name*）。您将需要存储该表的 Amazon Redshift 集群的 JDBC 连接信息。**您将提供连接信息，包括*主机*、*端口*、*redshift-database-name*、用户名*和密码*。

使用 Amazon Redshift 集群时，您可以从 Amazon Redshift 控制台检索连接信息。使用 Amazon Redshift Serverless 时，请参阅 Amazon Redshift 文档中的 [Connecting to Amazon Redshift Serverless](https://docs.aws.amazon.com//redshift/latest/mgmt/serverless-connecting.html)。

**配置：**在函数选项中，您将使用 `url`、`dbtable`、`user` 和 `password` 参数标识连接参数。您将使用 `redshift_tmp_dir` 标识 Amazon S3 临时目录。您可以在使用 `aws_iam_role` 时使用 `from_options` 来指定 IAM 角色。语法类似于通过 Data Catalog 进行连接，但您可以将参数放在 `connection_options` 地图中。

将密码硬编码为 AWS Glue 脚本不是好的做法。考虑使用 SDK for Python (Boto3) 将密码存储在 AWS Secrets Manager 中并检索。

```
my_conn_options = {  
    "url": "jdbc:redshift://host:port/redshift-database-name",
    "dbtable": "redshift-table-name",
    "user": "username",
    "password": "password",
    "redshiftTmpDir": args["temp-s3-dir"],
    "aws_iam_role": "arn:aws:iam::account id:role/rs-role-name"
}

df = glueContext.create_dynamic_frame.from_options("redshift", my_conn_options)
```

------

## 示例：写入 Amazon Redshift 表
<a name="aws-glue-programming-etl-connect-redshift-write"></a>

 您可以写入 Amazon Redshift 集群和 Amazon Redshift Serverless 环境。

**先决条件：**一个 Amazon Redshift 集群，以及按照上一节 [配置 Redshift 连接](#aws-glue-programming-etl-connect-redshift-configure) 中的步骤进行操作，之后您应该拥有临时目录 *temp-s3-dir* 和 IAM 角色 *rs-role-name* 的 Amazon S3 URI（在账户 *role-account-id* 中）。您还需要想写入数据库的内容的 `DynamicFrame`。

------
#### [ Using the Data Catalog ]

**其他先决条件：**您要对其写入的 Amazon Redshift 集群和表的 Data Catalog 数据库。有关 Data Catalog 的更多信息，请参阅 [AWS Glue 中的数据发现和编目](catalog-and-crawler.md)。您将使用 *redshift-dc-database-name* 标识连接，使用 *redshift-table-name* 标识目标表。

**配置：**在函数选项中，您将使用 `database` 参数标识 Data Catalog 数据库，并为表提供 `table_name`。您将使用 `redshift_tmp_dir` 标识 Amazon S3 临时目录。您还将使用 `additional_options` 参数中的 `aws_iam_role` 键提供 *rs-role-name*。

```
 glueContext.write_dynamic_frame.from_catalog(
    frame = input dynamic frame, 
    database = "redshift-dc-database-name", 
    table_name = "redshift-table-name", 
    redshift_tmp_dir = args["temp-s3-dir"], 
    additional_options = {"aws_iam_role": "arn:aws:iam::account-id:role/rs-role-name"})
```

------
#### [ Connecting through a AWS Glue connection ]

您可以使用 `write_dynamic_frame.from_options` 方法直接连接到 Amazon Redshift。但是，与其将连接详细信息直接插入脚本，不如使用 `from_jdbc_conf` 方法引用存储在 Data Catalog 连接中的连接详细信息。无需为数据库爬取或创建 Data Catalog 表，即可执行此操作。有关 Data Catalog 连接的更多信息，请参阅 [连接到数据](glue-connections.md)。

**其他先决条件：**您要从中读取 Amazon Redshift 表的数据库的 Data Catalog 连接。

**配置：**您将使用 *dc-connection-name* 标识 Data Catalog 连接。*您将使用 *redshift-table-name* 和 redshift-database-name* 标识 Amazon Redshift 数据库和表。您将使用 `catalog_connection` 提供 Data Catalog 连接信息，使用 `dbtable` 和 `database` 提供 Amazon Redshift 信息。语法类似于通过 Data Catalog 进行连接，但您可以将参数放在 `connection_options` 地图中。

```
my_conn_options = {
    "dbtable": "redshift-table-name",
    "database": "redshift-database-name",
    "aws_iam_role": "arn:aws:iam::role-account-id:role/rs-role-name"
}

glueContext.write_dynamic_frame.from_jdbc_conf(
    frame = input dynamic frame, 
    catalog_connection = "dc-connection-name", 
    connection_options = my_conn_options, 
    redshift_tmp_dir = args["temp-s3-dir"])
```

------

## Amazon Redshift 连接选项参考
<a name="w2aac67c11c24b8c21c15"></a>

用于所有 AWS Glue JDBC 连接的基本连接选项在所有 JDBC 类型中都是一致的，用于设置 `url`、`user` 和 `password` 之类的信息。有关标准 JDBC 参数的更多信息，请参阅 [JDBC 连接选项参考](aws-glue-programming-etl-connect-jdbc-home.md#aws-glue-programming-etl-connect-jdbc)。

Amazon Redshift 连接类型需要一些额外的连接选项：
+ `"redshiftTmpDir"`：（必需）从数据库中复制时，可以用于暂存临时数据的 Amazon S3 路径。
+ `"aws_iam_role"`：（可选）IAM 角色的 ARN。AWS Glue 作业会将此角色传递给 Amazon Redshift 集群，以授予完成作业指令所需的集群权限。

### AWS Glue 4.0\$1 版本中提供了其他连接选项
<a name="aws-glue-programming-etl-redshift-enhancements"></a>

您也可以通过 AWS Glue 连接选项传递新的 Amazon Redshift 连接器的选项。有关支持的连接器选项的完整列表，请参阅[适用于 Apache Spark 的 Amazon Redshift 集成](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)中的 *Spark SQL 参数*部分。

为方便起见，我们在此重申某些新选项：


| 名称 | 必需 | 默认值 | 说明 | 
| --- | --- | --- | --- | 
|  autopushdown  | 否 | TRUE |  通过捕获和分析 SQL 操作的 Spark 逻辑计划，应用谓词和查询下推。这些操作转换为 SQL 查询，然后在 Amazon Redshift 中运行以提高性能。  | 
|  autopushdown.s3\$1result\$1cache  | 否 | FALSE |  缓存 SQL 查询以将 Amazon S3 路径映射的数据卸载到内存中，以便同一查询不需要在同一 Spark 会话中再次运行。仅在启用 `autopushdown` 时支持。  | 
|  unload\$1s3\$1format  | 否 | PARQUET |  PARQUET — 以 Parquet 格式卸载查询结果。 TEXT — 以竖线分隔的文本格式卸载查询结果。  | 
|  sse\$1kms\$1key  | 否 | 不适用 |  在 `UNLOAD` 操作期间用于加密的 AWS SSE-KMS 密钥，而不是 AWS 的默认加密。  | 
|  extracopyoptions  | 否 | 不适用 |  加载数据时附加到 Amazon Redshift `COPY`命令的额外选项列表，例如 `TRUNCATECOLUMNS` 或 `MAXERROR n`（有关其他选项，请参阅 [COPY: Optional 参数](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY.html#r_COPY-syntax-overview-optional-parameters)）。 请注意，由于这些选项附加到 `COPY` 命令的末尾，因此只能使用在命令末尾有意义的选项。这应该涵盖最有可能的使用案例。  | 
|  cvsnullstring（实验）  | 否 | NULL |  使用 CSV `tempformat` 时要为空值写入的字符串值。这应该是一个不会出现在实际数据中的值。  | 

这些新参数可以通过以下方式使用。

**提高性能的新选项**  
新的连接器推出了一些新的性能改进选项：
+ `autopushdown`：默认情况下启用。
+ `autopushdown.s3_result_cache`：默认情况下禁用。
+ `unload_s3_format`：默认为 `PARQUET`。

有关使用这些选项的信息，请参阅[适用于 Apache Spark 的 Amazon Redshift 集成](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)。我们建议您在进行混合读取和写入操作时不要开启 ` autopushdown.s3_result_cache`，因为缓存的结果可能包含过时的信息。`UNLOAD` 命令的默认选项 `unload_s3_format` 设置为 `PARQUET`，以提高性能并降低存储成本。要使用 `UNLOAD` 命令的默认行为，请将该选项重置为 `TEXT`。

**新的读取加密选项**  
默认情况下，从 Amazon Redshift 表读取数据时，AWS Glue 使用的临时文件夹中的数据使用 `SSE-S3` 加密进行加密。要使用来自 AWS Key Management Service（AWS KMS）的客户自主管理型密钥来加密您的数据，您可以设置 `("sse_kms_key" → kmsKey)`，其中 ksmKey 是[来自 AWS KMS 的密钥 ID](https://docs.aws.amazon.com/kms/latest/developerguide/find-cmk-id-arn.html)，而不是 AWS Glue 版本 3.0 中的传统设置选项 `("extraunloadoptions" → s"ENCRYPTED KMS_KEY_ID '$kmsKey'")`。

```
datasource0 = glueContext.create_dynamic_frame.from_catalog(
  database = "database-name", 
  table_name = "table-name", 
  redshift_tmp_dir = args["TempDir"],
  additional_options = {"sse_kms_key":"<KMS_KEY_ID>"}, 
  transformation_ctx = "datasource0"
)
```

**支持基于 IAM 的 JDBC URL**  
新的连接器支持基于 IAM 的 JDBC URL，因此您无需传递用户/密码或密钥。通过基于 IAM 的 JDBC URL，连接器可使用作业运行时角色访问 Amazon Redshift 数据源。

步骤 1：将以下最低要求策略附加到您的 AWS Glue 作业运行时角色。

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "redshift:GetClusterCredentials",
            "Resource": [
                "arn:aws:redshift:us-east-1:111122223333:dbgroup:<cluster name>/*",
                "arn:aws:redshift:*:111122223333:dbuser:*/*",
                "arn:aws:redshift:us-east-1:111122223333:dbname:<cluster name>/<database name>"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "redshift:DescribeClusters",
            "Resource": "*"
        }
    ]
}
```

------

步骤 2：使用基于 IAM 的 JDBC URL，如下所示。使用您连接的 Amazon Redshift 用户名指定一个新选项 `DbUser`。

```
conn_options = {
     // IAM-based JDBC URL
    "url": "jdbc:redshift:iam://<cluster name>:<region>/<database name>",
    "dbtable": dbtable,
    "redshiftTmpDir": redshiftTmpDir,
    "aws_iam_role": aws_iam_role,
    "DbUser": "<Redshift User name>" // required for IAM-based JDBC URL
    }

redshift_write = glueContext.write_dynamic_frame.from_options(
    frame=dyf,
    connection_type="redshift",
    connection_options=conn_options
)

redshift_read = glueContext.create_dynamic_frame.from_options(
    connection_type="redshift",
    connection_options=conn_options
)
```

**注意**  
`DynamicFrame` 目前在 `GlueContext.create_dynamic_frame.from_options` 工作流程中仅支持对 ` DbUser` 使用基于 IAM 的 JDBC URL。

## 从 AWS Glue 版本 3.0 迁移到版本 4.0
<a name="aws-glue-programming-etl-redshift-migrating"></a>

在 AWS Glue 版本 4.0 中，ETL 作业可以访问新 Amazon Redshift Spark 连接器和新 JDBC 驱动程序，但选项和配置不同。全新 Amazon Redshift 连接器和驱动程序在编写时充分考虑了性能，可保持数据的交易一致性。这些产品记录在 Amazon Redshift 文档中。有关更多信息，请参阅：
+ [适用于 Apache Spark 的 Amazon Redshift 集成](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)
+ [Amazon Redshift JDBC 驱动程序版本 2.1](https://docs.aws.amazon.com/redshift/latest/mgmt/jdbc20-download-driver.html)

**表/列名和标识符限制**  
新的 Amazon Redshift Spark 连接器和驱动程序对 Redshift 表名称的要求更为严格。有关更多信息，请参阅[名称和标识符](https://docs.aws.amazon.com/redshift/latest/dg/r_names.html)以定义您的 Amazon Redshift 表名称。作业书签工作流程可能不适用于不符合规则的表名和某些字符（例如空格）。

如果您的旧表的名称不符合[名称和标识符](https://docs.aws.amazon.com/redshift/latest/dg/r_names.html)规则，并且发现书签存在问题（作业正在重新处理旧的 Amazon Redshift 表数据），我们建议您重命名表名。有关更多信息，请参阅[修改表示例](https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE_examples_basic.html)。

**数据帧中的默认临时格式更改**  
在写入到 Amazon Redshift 时，AWS Glue 版本 3.0 Spark 连接器会将 `tempformat` 的默认值设置为 CSV。为了保持一致，在 AWS Glue 3.0 版中，` DynamicFrame` 仍会将 `tempformat` 的默认值设置为使用 `CSV`。如果您之前曾在 Amazon Redshift Spark 连接器上直接使用过 Spark Dataframe API，则可以在 `DataframeReader`/`Writer` 选项中将 `tempformat` 明确设置为 CSV。否则，`tempformat` 在新 Spark 连接器中默认为 `AVRO`。

**行为更改：将 Amazon Redshift 数据类型 REAL 映射到 Spark 数据类型 FLOAT，而不是 DOUBLE**  
在 AWS Glue 3.0 版本中，Amazon Redshift `REAL` 被转换为 Spark ` DOUBLE` 类型。新的 Amazon Redshift Spark 连接器更新了行为，因此 Amazon Redshift ` REAL` 类型可以转换为 Spark `FLOAT` 类型，然后从这一类型转换回来。如果您的旧用例仍希望将 Amazon Redshift `REAL` 类型映射到 Spark `DOUBLE` 类型，则可以使用以下解决方法：
+ 对于 `DynamicFrame`，使用 `DynamicFrame.ApplyMapping` 将 `Float` 类型映射到 `Double` 类型。对于 `Dataframe`，需要使用 `cast`。

代码示例：

```
dyf_cast = dyf.apply_mapping([('a', 'long', 'a', 'long'), ('b', 'float', 'b', 'double')])
```

**处理 VARBYTE 数据类型**  
在处理 AWS Glue 3.0 和 Amazon Redshift 数据类型时，AWS Glue 3.0 会将 Amazon Redshift `VARBYTE` 转换为 Spark `STRING` 类型。但是，最新的 Amazon Redshift Spark 连接器不支持 `VARBYTE` 数据类型。要解决此限制，您可以[创建一个 Redshift 视图](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html)，将 `VARBYTE` 列转换为支持的数据类型。然后，使用新的连接器从此视图（而不是原始表）加载数据，这样既能确保兼容性，又能保持对 `VARBYTE` 数据的访问。

Redshift 查询示例：

```
CREATE VIEW view_name AS SELECT FROM_VARBYTE(varbyte_column, 'hex') FROM table_name
```

# Kafka 连接
<a name="aws-glue-programming-etl-connect-kafka-home"></a>

您可以使用 Kafka 连接来对 Kafka 数据流执行读取和写入操作，方法是通过存储在 Data Catalog 表中的信息进行读取和写入，或通过提供信息直接访问数据流。该连接支持 Kafka 集群或 Amazon Managed Streaming for Apache Kafka 集群。您可以将 Kafka 中的信息读取到 Spark DataFrame 中，然后将其转换为 AWS Glue DynamicFrame。您可以用 JSON 格式将 DynamicFrames 写入 Kafka。如果直接访问数据流，请使用这些选项提供有关如何访问数据流的信息。

如果您通过 `getCatalogSource` 或 `create_data_frame_from_catalog` 来使用来自 Kafka 流式处理源的记录，或通过 `getCatalogSink` 或 `write_dynamic_frame_from_catalog` 将记录写入 Kafka，则作业具有 Data Catalog 数据库和表名称信息，并且可以使用该信息来获取一些基本参数，以便从 Kafka 流式处理源读取数据。如果使用 `getSource`、`getCatalogSink`、`getSourceWithFormat`、`getSinkWithFormat`、`createDataFrameFromOptions`、`create_data_frame_from_options` 或 `write_dynamic_frame_from_catalog`，则必须使用此处描述的连接选项指定这些基本参数。

您可以使用 `GlueContext` 类中指定方法的以下参数为 Kafka 指定连接选项。
+ Scala
  + `connectionOptions`：与 `getSource`、`createDataFrameFromOptions`、`getSink` 结合使用 
  + `additionalOptions`：与 `getCatalogSource`、`getCatalogSink` 结合使用
  + `options`：与 `getSourceWithFormat`、`getSinkWithFormat` 结合使用
+ Python
  + `connection_options`：与 `create_data_frame_from_options`、`write_dynamic_frame_from_options` 结合使用
  + `additional_options`：与 `create_data_frame_from_catalog`、`write_dynamic_frame_from_catalog` 结合使用
  + `options`：与 `getSource`、`getSink` 结合使用

有关流式处理 ETL 作业的注意事项和限制，请参阅 [串流 ETL 注释和限制](add-job-streaming.md#create-job-streaming-restrictions)。

**Topics**
+ [

## 配置 Kafka
](#aws-glue-programming-etl-connect-kafka-configure)
+ [

## 示例：从 Kafka 流读取
](#aws-glue-programming-etl-connect-kafka-read)
+ [

## 示例：写入 Kafka 流
](#aws-glue-programming-etl-connect-kafka-write)
+ [

## Kafka 连接选项参考
](#aws-glue-programming-etl-connect-kafka)

## 配置 Kafka
<a name="aws-glue-programming-etl-connect-kafka-configure"></a>

连接到可通过互联网访问的 Kafka 流没有任何 AWS 先决条件。

您可以创建 AWS Glue Kafka 连接来管理连接凭证。有关更多信息，请参阅 [为 Apache Kafka 数据流创建 AWS Glue 连接](add-job-streaming.md#create-conn-streaming)。在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**，然后在方法调用中为 `connectionName` 参数提供 *connectionName*。

在某些情况下，您需要配置其他先决条件：
+ 如果使用 Amazon Managed Streaming for Apache Kafka 搭配 IAM 身份验证，则需要适当的 IAM 配置。
+ 如果在 Amazon VPC 内使用 Amazon Managed Streaming for Apache Kafka，则需要适当的 Amazon VPC 配置。您需要创建一个提供 Amazon VPC 连接信息的 AWS Glue 连接。您需要在作业配置中将 AWS Glue 连接作为**附加网络连接**包括在内。

有关流式处理 ETL 作业先决条件的更多信息，请参阅 [在 AWS Glue 中流式处理 ETL 作业](add-job-streaming.md)。

## 示例：从 Kafka 流读取
<a name="aws-glue-programming-etl-connect-kafka-read"></a>

与 [forEachBatch](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-forEachBatch) 结合使用。

Kafka 流式处理源示例：

```
kafka_options =
    { "connectionName": "ConfluentKafka", 
      "topicName": "kafka-auth-topic", 
      "startingOffsets": "earliest", 
      "inferSchema": "true", 
      "classification": "json" 
    }
data_frame_datasource0 = glueContext.create_data_frame.from_options(connection_type="kafka", connection_options=kafka_options)
```

## 示例：写入 Kafka 流
<a name="aws-glue-programming-etl-connect-kafka-write"></a>

写入 Kafka 的示例：

`getSink` 方法示例：

```
data_frame_datasource0 = 
glueContext.getSink(
	connectionType="kafka",
	connectionOptions={
		JsonOptions("""{
			"connectionName": "ConfluentKafka", 
			"classification": "json", 
			"topic": "kafka-auth-topic", 
			"typeOfData": "kafka"}
		""")}, 
	transformationContext="dataframe_ApacheKafka_node1711729173428")
	.getDataFrame()
```

`write_dynamic_frame.from_options` 方法示例：

```
kafka_options =
    { "connectionName": "ConfluentKafka", 
      "topicName": "kafka-auth-topic", 
      "classification": "json" 
    }
data_frame_datasource0 = glueContext.write_dynamic_frame.from_options(connection_type="kafka", connection_options=kafka_options)
```

## Kafka 连接选项参考
<a name="aws-glue-programming-etl-connect-kafka"></a>

在读取时，可以使用以下连接选项和 `"connectionType": "kafka"`：
+ `"bootstrap.servers"`（必需）引导服务器 URL 的列表，例如，作为 `b-1.vpc-test-2.o4q88o.c6.kafka.us-east-1.amazonaws.com:9094`。此选项必须在 API 调用中指定，或在数据目录的表元数据中定义。
+ `"security.protocol"`（必填）用于与代理通信的协议。可能的值为 `"SSL"` 或 `"PLAINTEXT"`。
+ `"topicName"`（必填）要订阅的以逗号分隔的主题列表。您必须指定`"topicName"`、`"assign"` 或 `"subscribePattern"` 中的其中一个，且只能指定一个。
+ `"assign"`：（必填）用于指定要使用的 `TopicPartitions` 的 JSON 字符串。您必须指定`"topicName"`、`"assign"` 或 `"subscribePattern"` 中的其中一个，且只能指定一个。

  例如：“\$1"topicA":[0,1],"topicB":[2,4]\$1”
+ `"subscribePattern"`：（必需）标识要订阅的主题列表的 Java 正则表达式字符串。您必须指定`"topicName"`、`"assign"` 或 `"subscribePattern"` 中的其中一个，且只能指定一个。

  示例：“topic.\$1”
+ `"classification"`（必需）记录中数据使用的文件格式。除非 Data Catalog 提供，否则为必需。
+ `"delimiter"`（可选）当 `classification` 为 CSV 时使用的值分隔符。默认为“`,`”。
+ `"startingOffsets"`：（可选）Kafka 主题中数据读取的起始位置。可能的值为 `"earliest"` 或 `"latest"`。默认值为 `"latest"`。
+ `"startingTimestamp"`：（可选，仅 AWS Glue 4.0 或更高版本支持）Kafka 主题中数据读取的记录的时间戳。可能的值是以模式 `yyyy-mm-ddTHH:MM:SSZ` 采用 UTC 格式的时间戳字符串（其中 `Z` 表示带有 \$1/-的 UTC 时区偏移量。例如：“2023-04-04T08:00:00-04:00”）。

  注意：AWS Glue 流式处理脚本的“连接选项”列表中只能出现“startingOffsets”或“startingTimestamp”中的一个，同时包括这两个属性会导致作业失败。
+ `"endingOffsets"`：（可选）批处理查询结束时的终点。可能值为 `"latest"`，或者为每个 `TopicPartition` 指定结束偏移的 JSON 字符串。

  对于 JSON 字符串，格式为 `{"topicA":{"0":23,"1":-1},"topicB":{"0":-1}}`。偏移值 `-1` 表示 `"latest"`。
+ `"pollTimeoutMs"`：（可选）Spark 任务执行程序中，从 Kafka 轮询数据的超时时间（以毫秒为单位）。默认值为 `600000`。
+ `"numRetries"`：（可选）无法获取 Kafka 偏移时的重试次数。默认值为 `3`。
+ `"retryIntervalMs"`：（可选）重试获取 Kafka 偏移时的等待时间（以毫秒为单位）。默认值为 `10`。
+ `"maxOffsetsPerTrigger"`：（可选）每个触发间隔处理的最大偏移数的速率限制。指定的总偏移数跨不同卷的 `topicPartitions` 按比例分割。默认值为 null，这意味着使用者读取所有偏移，直到已知的最新偏移。
+ `"minPartitions"`：（可选）从 Kafka 读取数据的必需最小分区数。默认值为 null，这意味着 Spark 分区数等于 Kafka 分区数。
+  `"includeHeaders"`：（可选）是否包含 Kafka 标头。当选项设置为“true”时，数据输出将包含一个名为“glue\$1streaming\$1kafka\$1headers”的附加列，类型为 `Array[Struct(key: String, value: String)]`。默认值为“false”。此选项仅适用于 AWS Glue 版本 3.0 或更高版本。
+ `"schema"`：（当 inferSchema 设为 false 时为必填）用于处理有效工作负载的架构。如果分类为 `avro`，则提供的架构必须采用 Avro 架构格式。如果分类不是 `avro`，则提供的架构必须采用 DDL 架构格式。

  以下是一些架构示例。

------
#### [ Example in DDL schema format ]

  ```
  'column1' INT, 'column2' STRING , 'column3' FLOAT
  ```

------
#### [ Example in Avro schema format ]

  ```
  {
  "type":"array",
  "items":
  {
  "type":"record",
  "name":"test",
  "fields":
  [
    {
      "name":"_id",
      "type":"string"
    },
    {
      "name":"index",
      "type":
      [
        "int",
        "string",
        "float"
      ]
    }
  ]
  }
  }
  ```

------
+ `"inferSchema"`：（可选）默认值为“false”。如果设置为“true”，则会在运行时检测到 `foreachbatch` 内的有效工作负载中的架构。
+ `"avroSchema"`：（已弃用）用于指定 Avro 数据架构（使用 Avro 格式时）的参数。此参数现已被弃用。使用 `schema` 参数。
+ `"addRecordTimestamp"`：（可选）当选项设置为 'true' 时，数据输出将包含一个名为 "\$1\$1src\$1timestamp" 的附加列，表示主题收到相应记录的时间。默认值为‘false’。4.0 或更高 AWS Glue 版本支持此选项。
+ `"emitConsumerLagMetrics"`：（可选）当该选项设置为 'true' 时，对于每个批次，它会向 CloudWatch 发布主题收到的最早记录与该记录到达 AWS Glue 之间的时长指标。指标名称为 "glue.driver.streaming.maxConsumerLagInMs"。默认值为‘false’。4.0 或更高 AWS Glue 版本支持此选项。

在写入时，可以使用以下连接选项和 `"connectionType": "kafka"`：
+ `"connectionName"`（必填项）用于连接到 Kafka 集群（类似于 Kafka 源）的 AWS Glue 连接的名称。
+ `"topic"`（必填项）如果存在主题列，则在将给定行写入 Kafka 时，除非设置了主题配置选项，否则其值将用作主题。也就是说，`topic` 配置选项会覆盖主题列。
+ `"partition"`（可选）如果指定了有效的分区号，则 `partition` 将在发送记录时使用该分区号。

  如果未指定分区但存在 `key`，则将使用该键的哈希值来选择分区。

  如果 `key` 和 `partition` 都不存在，则将根据在向分区至少生成了 batch.size 字节的数据时，对这些更改进行粘性分区来选择分区。
+ `"key"`（可选）如果 `partition` 为空，则用于分区。
+ `"classification"`（可选）记录中数据使用的文件格式。我们只支持 JSON、CSV 和 Avro。

  对于 Avro 格式，我们可以提供自定义 avroSchema 来进行序列化，但请注意，还需要在源中提供该格式以进行反序列化。否则，默认情况下它将使用 Apache AvroSchema 进行序列化。

此外，您可以在需要时通过更新 [Kafka 生产者配置参数](https://kafka.apache.org/documentation/#producerconfigs)来微调 Kafka 接收器。请注意，不存在有关连接选项的允许列表，所有键值对都按原样保存在接收器上。

虽然存在一个很小的选项拒绝列表，不过不会生效。有关更多信息，请参阅 [Kafka specific configurations](https://spark.apache.org/docs/latest/structured-streaming-kafka-integration.html)。

# Azure Cosmos DB 连接
<a name="aws-glue-programming-etl-connect-azurecosmos-home"></a>

借助 NoSQL API，您可以在 AWS Glue 4.0 及更高版本中使用 AWS Glue for Spark 读取和写入 Azure Cosmos DB 中现有的容器。您可以使用 SQL 查询来定义要从 Azure Cosmos DB 中读取的信息。您可以通过 AWS Glue 连接，使用存储在 AWS Secrets Manager 中的 Azure Cosmos DB 密钥连接到 Azure Cosmos DB。

有关 Azure Cosmos DB for NoSQL 的更多信息，请参阅 [Azure 文档](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/)。

## 配置 Azure Cosmos DB 连接
<a name="aws-glue-programming-etl-connect-azurecosmos-configure"></a>

要从 AWS Glue 连接到 Azure Cosmos DB，您需要创建一个 Azure Cosmos DB 密钥并将其存储在一个 AWS Secrets Manager 密钥中，然后将该密钥关联到某个 Azure Cosmos DB AWS Glue 连接。

**先决条件** 
+ 在 Azure 中，您需要确定或生成一个 Azure Cosmos DB 密钥 `cosmosKey`，以供 AWS Glue 使用。有关更多信息，请参阅 Azure 文档中的 [保护对 Azure Cosmos DB 中数据的访问](https://learn.microsoft.com/en-us/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key)。

**配置 Azure Cosmos DB 连接：**

1. 在 AWS Secrets Manager 中，使用您的 Azure Cosmos DB 密钥创建一个密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `spark.cosmos.accountKey` 和值 *cosmosKey* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名为 *connectionName*，以供未来在 AWS Glue 中使用。
   + 选择**连接类型**时，请选择 Azure Cosmos DB。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

创建 AWS Glue Azure Cosmos DB 连接后，您需要完成以下操作，然后才能运行 AWS Glue 作业：
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 读取 Azure Cosmos DB for NoSQL 容器
<a name="aws-glue-programming-etl-connect-azurecosmos-read"></a>

**先决条件** 
+ 您要读取的 Azure Cosmos DB for NoSQL 容器。您将需要该容器的标识信息。

  Azure Cosmos DB for NoSQL 容器由其数据库和容器来标识。在连接到 Azure Cosmos for NoSQL API 时，您必须提供数据库 *cosmosDBName* 和容器 *cosmosContainerName* 的名称。
+ 为了提供身份验证和网络位置信息而配置的 AWS Glue Azure Cosmos DB 连接。要获得此信息，请完成前面“配置 Azure Cosmos DB 连接”**中的步骤。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
azurecosmos_read = glueContext.create_dynamic_frame.from_options(
    connection_type="azurecosmos",
    connection_options={
    "connectionName": connectionName,
    "spark.cosmos.database": cosmosDBName,
    "spark.cosmos.container": cosmosContainerName,
    }
)
```

您还可以提供 SELECT SQL 查询来筛选返回到 DynamicFrame 的结果。您将需要配置 `query`。

例如：

```
azurecosmos_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="azurecosmos",
    connection_options={
        "connectionName": "connectionName",
        "spark.cosmos.database": cosmosDBName,
        "spark.cosmos.container": cosmosContainerName,
        "spark.cosmos.read.customQuery": "query"
    }
)
```

## 写入 Azure Cosmos DB for NoSQL 容器
<a name="aws-glue-programming-etl-connect-azurecosmos-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 Azure Cosmos DB。如果容器中已经含有信息，AWS Glue 会将来自 DynamicFrame 的数据附加到现有信息之后。如果容器中的信息与您写入的信息具有不同的 Schema，则会出现错误。

**先决条件** 
+ 您要写入的 Azure Cosmos DB 表。您将需要该容器的标识信息。**必须首先创建容器，然后才能调用连接方法。**

  Azure Cosmos DB for NoSQL 容器由其数据库和容器来标识。在连接到 Azure Cosmos for NoSQL API 时，您必须提供数据库 *cosmosDBName* 和容器 *cosmosContainerName* 的名称。
+ 为了提供身份验证和网络位置信息而配置的 AWS Glue Azure Cosmos DB 连接。要获得此信息，请完成前面“配置 Azure Cosmos DB 连接”**中的步骤。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
azurecosmos_write = glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="azurecosmos",
    connection_options={
    "connectionName": connectionName,
    "spark.cosmos.database": cosmosDBName,
    "spark.cosmos.container": cosmosContainerName
)
```

## Azure Cosmos DB 连接选项参考
<a name="aws-glue-programming-etl-connect-azurecosmos-reference"></a>
+ `connectionName` – 必需。用于读/写。为了向您的连接方法提供身份验证和网络位置信息而配置的 AWS Glue Azure Cosmos DB 连接的名称。
+ `spark.cosmos.database` – 必需。用于读/写。有效值：数据库名。Azure Cosmos DB for NoSQL 数据库名。
+ `spark.cosmos.container` – 必需。用于读/写。有效值：容器名。Azure Cosmos DB for NoSQL 容器名。
+ `spark.cosmos.read.customQuery` – 用于读取。有效值：SELECT SQL 查询。用于选择要读取的文档的自定义查询。

# Azure SQL 连接
<a name="aws-glue-programming-etl-connect-azuresql-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 来读取和写入 Azure SQL 托管实例中的表。您可以使用 SQL 查询来定义要从 Azure SQL 中读取的信息。您可以通过 AWS Glue 连接并使用存储在 AWS Secrets Manager 中的用户名和密码凭证连接到 Azure SQL。

有关 Azure SQL 的更多信息，请参阅 [Azure SQL 文档](https://azure.microsoft.com/en-us/products/azure-sql)。

## 配置 Azure SQL 连接
<a name="aws-glue-programming-etl-connect-azuresql-configure"></a>

要从 AWS Glue 连接到 Azure SQL，您需要创建 Azure SQL 凭证并将其存储在一个 AWS Secrets Manager 密钥中，然后将该密钥关联到某个 Azure SQL AWS Glue 连接。

**配置 Azure SQL 连接：**

1. 在 AWS Secrets Manager 中，使用您的 Azure SQL 凭证创建密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `user` 和值 *azuresqlUsername* 创建一个键值对。
   + 在选择**键/值对**时，请使用键 `password` 和值 *azuresqlPassword* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名为 *connectionName*，以供未来在 AWS Glue 中使用。
   + 选择**连接类型**时，请选择 Azure SQL。
   + 在提供 **Azure SQL URL** 时，请提供 JDBC 端点的 URL。

      该 URL 必须为以下格式：`jdbc:sqlserver://databaseServerName:databasePort;databaseName=azuresqlDBname;`。

     AWS Glue 需要以下 URL 属性：
     + `databaseName` – Azure SQL 中要连接的默认数据库。

     有关 Azure SQL 托管实例的 JDBC URL 的更多信息，请参阅 [Microsoft 文档](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=azuresqldb-mi-current)。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

创建 AWS Glue Azure SQL 连接后，您需要完成以下操作，然后才能运行 AWS Glue 作业：
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 读取 Azure SQL 表
<a name="aws-glue-programming-etl-connect-azuresql-read"></a>

**先决条件** 
+ 您要读取的 Azure SQL 表。您将需要表的标识信息 *databaseName* 和 *tableIdentifier*。

  Azure SQL 表由其数据库、Schema 和表名来标识。连接到 Azure SQL 时，必须提供数据库名和表名。如果 Schema 不是默认值“public”，则还必须提供 Schema。数据库通过 *connectionName* 中的 URL 属性来提供，Schema 和表名通过 `dbtable` 来提供。
+ 为了提供身份验证信息而配置的 AWS Glue Azure SQL 连接。完成上一节“配置 Azure SQL 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
azuresql_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type="azuresql",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableIdentifier"
    }
)
```

您还可以提供 SELECT SQL 查询来筛选返回到 DynamicFrame 的结果。您将需要配置 `query`。

例如：

```
azuresql_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="azuresql",
    connection_options={
        "connectionName": "connectionName",
        "query": "query"
    }
)
```

## 写入 Azure SQL 表
<a name="aws-glue-programming-etl-connect-azuresql-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 Azure SQL。如果表中已经含有信息，AWS Glue 会将来自 DynamicFrame 的数据附加到现有信息之后。

**先决条件** 
+ 您要写入的 Azure SQL 表。您将需要表的标识信息 *databaseName* 和 *tableIdentifier*。

  Azure SQL 表由其数据库、Schema 和表名来标识。连接到 Azure SQL 时，必须提供数据库名和表名。如果 Schema 不是默认值“public”，则还必须提供 Schema。数据库通过 *connectionName* 中的 URL 属性来提供，Schema 和表名通过 `dbtable` 来提供。
+ Azure SQL 身份验证信息。完成上一节“配置 Azure SQL 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
azuresql_write = glueContext.write_dynamic_frame.from_options(
    connection_type="azuresql",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableIdentifier"
    }
)
```

## Azure SQL 连接选项参考
<a name="aws-glue-programming-etl-connect-azuresql-reference"></a>
+ `connectionName` – 必需。用于读/写。为了向您的连接方法提供身份验证信息而配置的 AWS Glue Azure SQL 连接的名称。
+ `databaseName` - 用于读/写。有效值：Azure SQL 数据库名。要连接的 Azure SQL 数据库的名称。
+ `dbtable` – 对于写入为必填项，对于读取也为必填项，但提供了 `query` 时除外。用于读/写。有效值：Azure SQL 表名或用句点分隔的 Schema 名/表名组合。用于指定表和 Schema，以标识要连接的表。默认 Schema 为“public”。如果您的表并非使用默认 Schema，请在表单 `schemaName.tableName` 中提供此信息。
+ `query` – 用于读取。用来定义从 Azure SQL 读取数据时要检索的内容的 Transact-SQL SELECT 查询。有关更多信息，请参阅 [Microsoft 文档](https://learn.microsoft.com/en-us/sql/t-sql/queries/select-transact-sql?view=azuresqldb-mi-current)。

# BigQuery 连接
<a name="aws-glue-programming-etl-connect-bigquery-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 在 Google BigQuery 中读取和写入表。您可以通过 Google SQL 查询从 BigQuery 中读取。您可以通过 AWS Glue 连接使用存储在 AWS Secrets Manager 中的凭证连接到 BigQuery。

有关 Google BigQuery 的更多信息，请参见 [Google Cloud BigQuery 网站](https://cloud.google.com/bigquery)。

## 配置 BigQuery 连接
<a name="aws-glue-programming-etl-connect-bigquery-configure"></a>

要从 AWS Glue 中连接到 Google BigQuery，您需要创建 Google Cloud Platform 凭证并将其存储在 AWS Secrets Manager 密钥中，然后将该密钥与 Google BigQuery AWS Glue 连接关联。

**要配置与 BigQuery 的连接：**

1. 在 Google Cloud Platform，创建并识别相关资源：
   + 创建或标识包含您想要连接的 BigQuery 表的 GCP 项目。
   + 启用 BigQuery API。有关更多信息，请参阅[使用 BigQuery 存储读取 API 读取表数据](https://cloud.google.com/bigquery/docs/reference/storage/#enabling_the_api)。

1. 在 Google Cloud Platform 中，创建和导出服务账户凭证：

   您可以使用 BigQuery 凭证向导来加快此步骤：[创建凭证](https://console.cloud.google.com/apis/credentials/wizard?api=bigquery.googleapis.com)。

   要在 GCP 中创建服务账户，请按照[创建服务账户](https://cloud.google.com/iam/docs/service-accounts-create)中的教程进行操作。
   + 选择**项目**时，请选择包含您的 BigQuery 表的项目。
   + 为您的服务账户选择 GCP IAM 角色时，请添加或创建一个角色，该角色将授予运行 BigQuery 作业的相应权限，以读取、写入或创建 BigQuery 表。

   要为您的服务账户创建凭证，请按照[创建服务账户密钥](https://cloud.google.com/iam/docs/keys-create-delete#creating)中的教程进行操作。
   + 在选择密钥类型时，请选择 **JSON**。

   现在，您应该已经下载了包含服务账户凭证的 JSON 文件。如下所示：

   ```
   {
     "type": "service_account",
     "project_id": "*****",
     "private_key_id": "*****",
     "private_key": "*****",
     "client_email": "*****",
     "client_id": "*****",
     "auth_uri": "https://accounts.google.com/o/oauth2/auth",
     "token_uri": "https://oauth2.googleapis.com/token",
     "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
     "client_x509_cert_url": "*****",
     "universe_domain": "googleapis.com"
   }
   ```

1. 将您的凭证 JSON 文件上传到适当安全的 Amazon S3 位置。保留文件路径*s3secretpath* 以备将来的步骤使用。

1. 在 AWS Secrets Manager 中，使用您的 Google Cloud Platform 凭证创建密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。

   创建键/值对时，请按以下方式指定键和值：
   + 对于 `token_uri`、`client_x509_cert_url`、`private_key_id`、`project_id`、`universe_domain`、`auth_provider_x509_cert_url`、`auth_uri`、`client_email`、`private_key`、`type`、`client_id` 键，请在下载的 JSON 文件中指定相应的值。
   + 对于 `spark.hadoop.google.cloud.auth.service.account.json.keyfile` 键，请指定 *s3secretpath*。

1. 在 AWS Glue Data Catalog 中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建连接。创建连接后，保留连接名称 *connectionName*，以供下一步使用。
   + 在选择**连接类型**时，请选择 Google BigQuery。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

1. 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。

1. 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 从 BigQuery 表格中读取
<a name="aws-glue-programming-etl-connect-bigquery-read"></a>

**先决条件** 
+ 您想从中读取的 BigQuery 表。您需要 `[dataset].[table]` 形式的 BigQuery 表和数据集名称。我们称之为 *tableName*。
+ BigQuery 表的计费项目。您将需要项目的名称 *parentProject*。如果没有计费父项目，请使用包含该表的项目。
+ BigQuery 身份验证信息。完成*使用 AWS Glue 管理连接凭证*的步骤，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
bigquery_read = glueContext.create_dynamic_frame.from_options(
    connection_type="bigquery",
    connection_options={
        "connectionName": "connectionName",
        "parentProject": "parentProject",
        "sourceType": "table",
        "table": "tableName",
    }
```

您还可以提供查询，以筛选返回到您的 DynamicFrame 的结果。您将需要配置 `query`、`sourceType`、`viewsEnabled` 和 `materializationDataset`。

例如：

**其他先决条件：**

您需要创建或识别一个 BigQuery 数据集 *materializationDataset*，BigQuery 可以在其中为您的查询编写实体化视图。

您需要向您的服务账户授予相应的 GCP IAM 权限，才能在 *materializationDataset* 中创建表。

```
glueContext.create_dynamic_frame.from_options(
            connection_type="bigquery",
            connection_options={
                "connectionName": "connectionName",
                "materializationDataset": materializationDataset,
                "parentProject": "parentProject",
                "viewsEnabled": "true",
                "sourceType": "query",
                "query": "select * from bqtest.test"
            }
        )
```

## 写入 BigQuery 表
<a name="aws-glue-programming-etl-connect-bigquery-write"></a>

此示例直接写入 BigQuery 服务。BigQuery 还支持“间接”写入方法。有关配置间接写入的更多信息，请参阅 [在 Google BigQuery 中使用间接写入](#aws-glue-programming-etl-connect-bigquery-indirect-write)。

**先决条件** 
+ 您想向其中写入的 BigQuery 表。您需要 `[dataset].[table]` 形式的 BigQuery 表和数据集名称。您也可以提供一个将自动创建的新表名。我们称之为 *tableName*。
+ BigQuery 表的计费项目。您将需要项目的名称 *parentProject*。如果没有计费父项目，请使用包含该表的项目。
+ BigQuery 身份验证信息。完成*使用 AWS Glue 管理连接凭证*的步骤，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
bigquery_write = glueContext.write_dynamic_frame.from_options(
    frame=frameToWrite,
    connection_type="bigquery",
    connection_options={
        "connectionName": "connectionName",
        "parentProject": "parentProject",
        "writeMethod": "direct",
        "table": "tableName",
    }
)
```

## BigQuery 连接选项参考
<a name="aws-glue-programming-etl-connect-bigquery-reference"></a>
+ `project` – 默认：Google Cloud 服务账户默认。用于读/写。与您的表格关联的 Google Cloud 项目的名称。
+ `table` -（必需）用于读/写。格式为 `[[project:]dataset.]` 的 BigQuery 表的名称。
+ `dataset` – 如果未通过 `table` 选项进行定义，则为必填项。用于读/写。包含您的 BigQuery 表的数据集的名称。
+ `parentProject` – 默认：Google Cloud 服务账户默认。用于读/写。与用于计费的 `project` 关联的 Google Cloud 项目的名称。
+ `sourceType` – 用于读取。读取时为必填项。有效值：`table`，`query` 告知 AWS Glue 是按表读取还是按查询读取。
+ `materializationDataset` – 用于读取。有效值：字符串。用于存储视图实例化的 BigQuery 数据集的名称。
+ `viewsEnabled` – 用于读取。默认值：false。有效值：true、false。配置 BigQuery 是否使用视图。
+ `query` – 用于读取。在 `viewsEnabled` 为真时使用。GoogleSQL DQL 查询。
+ `temporaryGcsBucket` – 用于写入。在 `writeMethod` 设置为默认值（`indirect`）时为必填。写入 BigQuery 时用于存储中间形式数据的 Google Cloud Storage 存储桶的名称。
+ `writeMethod` - 默认值：`indirect`。有效值：`direct`、`indirect`。用于写入。指定用于写入数据的方法。
  + 如果设置为 `direct`，则您的连接器将使用 BigQuery 存储写入 API 进行写入。
  + 如果设置为 `indirect`，则您的连接器将 Google Cloud Storage，然后使用加载操作将其传输到 BigQuery。您的 Google Cloud 服务账户将需要相应的 GCS 权限。

## 在 Google BigQuery 中使用间接写入
<a name="aws-glue-programming-etl-connect-bigquery-indirect-write"></a>

此示例使用间接写入，将数据写入 Google Cloud Storage 并将其复制到 Google BigQuery。

**先决条件**

您需要一个临时的 Google Cloud Storage 存储桶 *temporaryBucket*。

AWS Glue 的 GCP 服务账户的 GCP IAM 角色需要适当的 GCS 权限才能访问 *temporaryBucket*。

**其他配置：**

**要使用 BigQuery 配置间接写入，请执行以下操作：**

1. 评测 [配置 BigQuery 连接](#aws-glue-programming-etl-connect-bigquery-configure) 并找到或重新下载您的 GCP 凭证 JSON 文件。识别 *SecretName*，这是您的作业中使用的 Google BigQuery AWS Glue 连接的 AWS Secrets Manager 密钥。

1. 将您的凭证 JSON 文件上传到适当安全的 Amazon S3 位置。保留文件路径*s3secretpath* 以备将来的步骤使用。

1. 编辑 *secretName*，添加 `spark.hadoop.google.cloud.auth.service.account.json.keyfile` 密钥。将值设置为 *s3secretpath*。

1. 向您的 AWS Glue 作业 Amazon S3 授予访问 *s3secretpath* 的 IAM 权限。

现在，您可以将临时 GCS 存储桶位置提供给您的写入方法。您无需提供 `writeMethod`，因为 `indirect` 历史上是默认设置。

```
bigquery_write = glueContext.write_dynamic_frame.from_options(
    frame=frameToWrite,
    connection_type="bigquery",
    connection_options={
        "connectionName": "connectionName",
        "parentProject": "parentProject",
        "temporaryGcsBucket": "temporaryBucket",
        "table": "tableName",
    }
)
```

# JDBC 连接
<a name="aws-glue-programming-etl-connect-jdbc-home"></a>

 某些（通常是关系型）数据库类型支持通过 JDBC 标准进行连接。有关 JDBC 的更多信息，请参阅 [Java JDBC API](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) 文档。AWSGlue 原生支持通过 JDBC 连接器连接到某些数据库，JDBC 库在 AWS Glue Spark 作业中提供。使用 AWS Glue 库连接到这些数据库类型时，您可以访问一组标准选项。

JDBC connectionType 值包括：
+ `"connectionType": "sqlserver"`：指定与 Microsoft SQL Server 数据库的连接。
+ `"connectionType": "mysql"`：指定与 MySQL 数据库的连接。
+ `"connectionType": "oracle"`：指定与 Oracle 数据库的连接。
+ `"connectionType": "postgresql"`：指定与 PostgreSQL 数据库的连接。
+ `"connectionType": "redshift"`：指定与 Amazon Redshift 数据库的连接。有关更多信息，请参阅 [Redshift 连接](aws-glue-programming-etl-connect-redshift-home.md)。

下表列出了 AWS Glue 支持的 JDBC 驱动程序版本。


| 产品 | Glue 5.1 的 JDBC 驱动程序版本 | Glue 5.0 的 JDBC 驱动程序版本 | Glue 4.0 的 JDBC 驱动程序版本 | Glue 3.0 的 JDBC 驱动程序版本 | Glue 0.9、1.0、2.0 的 JDBC 驱动程序版本 | 
| --- | --- | --- | --- | --- | --- | 
| Microsoft SQL Server | 10.2.0 | 10.2.0 | 9.4.0 | 7.x | 6.x | 
| MySQL | 8.0.33 | 8.0.33 | 8.0.23 | 8.0.23 | 5.1 | 
| Oracle Database | 23.3.0.23.09 | 23.3.0.23.09 | 21.7 | 21.1 | 11.2 | 
| PostgreSQL | 42.7.3 | 42.7.3 | 42.3.6 | 42.2.18 | 42.1.x | 
| Amazon Redshift \$1 | redshift-jdbc42-2.1.0.29 | redshift-jdbc42-2.1.0.29 | redshift-jdbc42-2.1.0.16 | redshift-jdbc41-1.2.12.1017 | redshift-jdbc41-1.2.12.1017 | 

\$1 如果是 Amazon Redshift 连接类型，用于 JDBC 连接的连接选项中包含的所有其他选项名称/值对（包括格式选项）将直接传递到底层 SparkSQL DataSource。在 AWS Glue 4.0 及更高版本的 AWS Glue with Spark 作业中，Amazon Redshift 的 AWS Glue 原生连接器使用适用于 Apache Spark 的 Amazon Redshift 集成。有关更多信息，请参阅 [Amazon Redshift integration for Apache Spark](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)。在之前的版本中，请参阅 [Amazon Redshift data source for Spark](https://github.com/databricks/spark-redshift)。

要将您的 Amazon VPC 配置为使用 JDBC 连接到 Amazon RDS 数据存储，请参阅 [设置 Amazon VPC 以建立从 AWS Glue 到 Amazon RDS 数据存储的 JDBC 连接](setup-vpc-for-glue-access.md)。

**注意**  
AWS Glue 作业在一次运行期间仅与一个子网关联。这可能会影响您使用同一作业连接到多个数据来源。此行为不仅限于 JDBC 源。

**Topics**
+ [

## JDBC 连接选项参考
](#aws-glue-programming-etl-connect-jdbc)
+ [

## 使用 sampleQuery
](#aws-glue-programming-etl-jdbc-samplequery)
+ [

## 使用自定义 JDBC 驱动程序
](#aws-glue-programming-etl-jdbc-custom-driver)
+ [

# 从 JDBC 表并行读取
](run-jdbc-parallel-read-job.md)
+ [

# 设置 Amazon VPC 以建立从 AWS Glue 到 Amazon RDS 数据存储的 JDBC 连接
](setup-vpc-for-glue-access.md)

## JDBC 连接选项参考
<a name="aws-glue-programming-etl-connect-jdbc"></a>

如果您已经定义了 JDBC AWS Glue 连接，则可以重复使用其中定义的配置属性，例如：url、用户和密码；不必在代码中将它们指定为连接选项。此功能只在 AWS Glue 3.0 及更高版本中提供。为此，请使用以下连接属性：
+ `"useConnectionProperties"`：设置为 "true" 以表示您要使用连接中的配置。
+ `"connectionName"`：输入要从中检索配置的连接名称，必须在与作业相同的区域中定义连接。

将这些连接选项与 JDBC 连接结合使用：
+ `"url"`：（必填）数据库的 JDBC URL。
+ `"dbtable"`：（必需）要从中读取数据的数据库表。对于在数据库中支持架构的 JDBC 数据存储，指定 `schema.table-name`。如果未提供架构，则使用默认的“public”架构。
+ `"user"`：（必需）在连接时使用的用户名。
+ `"password"`：（必填）在连接时使用的密码。
+ （可选）以下选项允许您提供自定义 JDBC 驱动程序。如果必须使用 AWS Glue 本身不支持的驱动程序，请使用这些选项。

  ETL 作业可以为数据源和目标使用不同的 JDBC 驱动程序版本，即使源和目标是相同的数据库产品也是如此。这允许您在不同版本的源数据库和目标数据库之间迁移数据。要使用这些选项，您必须首先将 JDBC 驱动程序的 JAR 文件上传到 Amazon S3。
  + `"customJdbcDriverS3Path"`：自定义 JDBC 驱动程序的 Amazon S3 路径。
  + `"customJdbcDriverClassName"`：JDBC 驱动程序的类名。
+ `"bulkSize"`：（可选）用于配置并行插入以加速批量加载到 JDBC 目标。为写入或插入数据时要使用的并行度指定整数值。此选项有助于提高写入数据库（如 Arch User Repository (AUR)）的性能。
+ `"hashfield"`（可选）一个字符串，用于指定 JDBC 表中一列的名称，用于在并行读取 JDBC 表时将数据划分为多个分区。提供“哈希字段”或“哈希表达式”。有关更多信息，请参阅 [从 JDBC 表并行读取](run-jdbc-parallel-read-job.md)。
+ `"hashexpression"`（可选）返回整数的 SQL 选择子句。用于在并行读取 JDBC 表时将 JDBC 表中的数据划分为多个分区。提供“哈希字段”或“哈希表达式”。有关更多信息，请参阅 [从 JDBC 表并行读取](run-jdbc-parallel-read-job.md)。
+ `"hashpartitions"`（可选）正整数。用于指定并行读取 JDBC 表时对 JDBC 表进行并行读取的次数。默认值：7。有关更多信息，请参阅 [从 JDBC 表并行读取](run-jdbc-parallel-read-job.md)。
+ `"sampleQuery"`：（可选）自定义 SQL 查询语句。用于指定表中信息的子集以检索表格内容的样本。**如果不考虑您的数据进行配置，则其效率可能低于 DynamicFrame 方法，从而导致超时或内存不足错误。**有关更多信息，请参阅 [使用 sampleQuery](#aws-glue-programming-etl-jdbc-samplequery)。
+ `"enablePartitioningForSampleQuery"`：（可选）布尔值。默认值：false。用于在指定 `sampleQuery` 时并行读取 JDBC 表。**如果设置为 true，`sampleQuery` 必须以“where”或“and”结尾，以便于 AWS Glue 追加分区条件。**有关更多信息，请参阅 [使用 sampleQuery](#aws-glue-programming-etl-jdbc-samplequery)。
+ `"sampleSize"`：（可选）正整数。限制示例查询返回的行数。仅当 `enablePartitioningForSampleQuery` 为 true 时有用。如果未启用分区，则应直接在 `sampleQuery` 中添加 `"limit x"` 以限制大小。有关更多信息，请参阅 [使用 sampleQuery](#aws-glue-programming-etl-jdbc-samplequery)。

## 使用 sampleQuery
<a name="aws-glue-programming-etl-jdbc-samplequery"></a>

本部分介绍如何设置 `sampleQuery`、`sampleSize` 和 `enablePartitioningForSampleQuery`。

`sampleQuery` 是对数据集的几行进行采样的有效方法。默认情况下，查询由单个执行程序执行。如果不考虑您的数据进行配置，则其效率可能低于 DynamicFrame 方法，从而导致超时或内存不足错误。通常仅出于性能考虑，才需要在底层数据库上运行 SQL 作为 ETL 管道的一部分。如果试图预览数据集的几行，请考虑使用 [show](aws-glue-api-crawler-pyspark-extensions-dynamic-frame.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-show)。如果您试图使用 SQL 转换数据集，请考虑使用 [toDF](aws-glue-api-crawler-pyspark-extensions-dynamic-frame.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-toDF)，在 DataFrame 表单中针对您的数据定义 SparkSQL 转换。

虽然您的查询可能会处理各种表，但 `dbtable` 仍然是必需的。

**使用 sampleQuery 检索表的样本**

当使用默认 sampleQuery 行为检索数据样本时，AWS Glue 预计吞吐量不会很大，因此它会在单个执行程序上运行查询。为了限制您提供的数据，以便不会导致性能问题，我们建议您为 SQL 提供一个 `LIMIT` 子句。

**Example 在不进行分区的情况下使用 samplQuery**  
以下代码示例演示了如何在不进行分区的情况下使用 `sampleQuery`。  

```
//A full sql query statement.
val query = "select name from $tableName where age > 0 limit 1"
val connectionOptions = JsonOptions(Map(
    "url" -> url, 
    "dbtable" -> tableName, 
    "user" -> user, 
    "password" -> password, 
    "sampleQuery" -> query ))
val dyf = glueContext.getSource("mysql", connectionOptions)
          .getDynamicFrame()
```

**对较大的数据集使用 sampleQuery**

 如果您读取的是大型数据集，则可能需要启用 JDBC 分区才能并行查询表。有关更多信息，请参阅 [从 JDBC 表并行读取](run-jdbc-parallel-read-job.md)。要将 `sampleQuery` 与 JDBC 分区一同使用，请将 `enablePartitioningForSampleQuery` 设置为 true。启用此功能需要您对自己的 `sampleQuery` 进行一些更改。

将 JDBC 分区与 `sampleQuery` 一起使用时，查询必须以“where”或“and”结尾，以便于 AWS Glue 附加分区条件。

 如果您想在并行读取 JDBC 表时限制 sampleQuery 的结果，请设置 `"sampleSize"` 参数而不是指定 `LIMIT` 子句。

**Example 将 sampleQuery 与 JDBC 分区一起使用**  
以下代码示例演示了如何将 `sampleQuery` 与 JDBC 分区一起使用。  

```
//note that the query should end with "where" or "and" if use with JDBC partitioning.
val query = "select name from $tableName where age > 0 and"

//Enable JDBC partitioning by setting hashfield.
//to use sampleQuery with partitioning, set enablePartitioningForSampleQuery.
//use sampleSize to limit the size of returned data.
val connectionOptions = JsonOptions(Map(
    "url" -> url, 
    "dbtable" -> tableName, 
    "user" -> user, 
    "password" -> password, 
    "hashfield" -> primaryKey,
    "sampleQuery" -> query,
    "enablePartitioningForSampleQuery" -> true,
    "sampleSize" -> "1" ))
val dyf = glueContext.getSource("mysql", connectionOptions)
          .getDynamicFrame()
```

 **注释和限制：**

示例查询不可以与作业书签一起使用。提供两者的配置时，书签状态将会被忽略。

## 使用自定义 JDBC 驱动程序
<a name="aws-glue-programming-etl-jdbc-custom-driver"></a>

以下代码示例演示了如何使用自定义 JDBC 驱动程序读取和写入 JDBC 数据库。这些示例演示了如何从一个版本的数据库产品读取和写入同一产品的更高版本。

------
#### [ Python ]

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext, SparkConf
from awsglue.context import GlueContext
from awsglue.job import Job
import time
from pyspark.sql.types import StructType, StructField, IntegerType, StringType

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

# Construct JDBC connection options
connection_mysql5_options = {
    "url": "jdbc:mysql://<jdbc-host-name>:3306/db",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd"}

connection_mysql8_options = {
    "url": "jdbc:mysql://<jdbc-host-name>:3306/db",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd",
    "customJdbcDriverS3Path": "s3://amzn-s3-demo-bucket/mysql-connector-java-8.0.17.jar",
    "customJdbcDriverClassName": "com.mysql.cj.jdbc.Driver"}

connection_oracle11_options = {
    "url": "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd"}

connection_oracle18_options = {
    "url": "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd",
    "customJdbcDriverS3Path": "s3://amzn-s3-demo-bucket/ojdbc10.jar",
    "customJdbcDriverClassName": "oracle.jdbc.OracleDriver"}

# Read from JDBC databases with custom driver
df_mysql8 = glueContext.create_dynamic_frame.from_options(connection_type="mysql",
                                                          connection_options=connection_mysql8_options)

# Read DynamicFrame from MySQL 5 and write to MySQL 8
df_mysql5 = glueContext.create_dynamic_frame.from_options(connection_type="mysql",
                                                          connection_options=connection_mysql5_options)
glueContext.write_from_options(frame_or_dfc=df_mysql5, connection_type="mysql",
                               connection_options=connection_mysql8_options)

# Read DynamicFrame from Oracle 11 and write to Oracle 18
df_oracle11 = glueContext.create_dynamic_frame.from_options(connection_type="oracle",
                                                            connection_options=connection_oracle11_options)
glueContext.write_from_options(frame_or_dfc=df_oracle11, connection_type="oracle",
                               connection_options=connection_oracle18_options)
```

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {
  val MYSQL_5_URI: String = "jdbc:mysql://<jdbc-host-name>:3306/db"
  val MYSQL_8_URI: String = "jdbc:mysql://<jdbc-host-name>:3306/db"
  val ORACLE_11_URI: String = "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL"
  val ORACLE_18_URI: String = "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL"

  // Construct JDBC connection options
  lazy val mysql5JsonOption = jsonOptions(MYSQL_5_URI)
  lazy val mysql8JsonOption = customJDBCDriverJsonOptions(MYSQL_8_URI, "s3://amzn-s3-demo-bucket/mysql-connector-java-8.0.17.jar", "com.mysql.cj.jdbc.Driver")
  lazy val oracle11JsonOption = jsonOptions(ORACLE_11_URI)
  lazy val oracle18JsonOption = customJDBCDriverJsonOptions(ORACLE_18_URI, "s3://amzn-s3-demo-bucket/ojdbc10.jar", "oracle.jdbc.OracleDriver")

  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    // Read from JDBC database with custom driver
    val df_mysql8: DynamicFrame = glueContext.getSource("mysql", mysql8JsonOption).getDynamicFrame()

    // Read DynamicFrame from MySQL 5 and write to MySQL 8
    val df_mysql5: DynamicFrame = glueContext.getSource("mysql", mysql5JsonOption).getDynamicFrame()
    glueContext.getSink("mysql", mysql8JsonOption).writeDynamicFrame(df_mysql5)

    // Read DynamicFrame from Oracle 11 and write to Oracle 18
    val df_oracle11: DynamicFrame = glueContext.getSource("oracle", oracle11JsonOption).getDynamicFrame()
    glueContext.getSink("oracle", oracle18JsonOption).writeDynamicFrame(df_oracle11)

    Job.commit()
  }

  private def jsonOptions(url: String): JsonOptions = {
    new JsonOptions(
      s"""{"url": "${url}",
         |"dbtable":"test",
         |"user": "admin",
         |"password": "pwd"}""".stripMargin)
  }

  private def customJDBCDriverJsonOptions(url: String, customJdbcDriverS3Path: String, customJdbcDriverClassName: String): JsonOptions = {
    new JsonOptions(
      s"""{"url": "${url}",
         |"dbtable":"test",
         |"user": "admin",
         |"password": "pwd",
         |"customJdbcDriverS3Path": "${customJdbcDriverS3Path}",
         |"customJdbcDriverClassName" : "${customJdbcDriverClassName}"}""".stripMargin)
  }
}
```

------

# 从 JDBC 表并行读取
<a name="run-jdbc-parallel-read-job"></a>

您可以设置 JDBC 表的属性，以使 AWS Glue 并行读取数据。当您设置某些属性时，您可以指示 AWS Glue 对数据的逻辑分区运行并行 SQL 查询。您可以通过设置哈希字段或哈希表达式来控制分区。您还可以控制用于访问您的数据的并行读取的数量。

并行读取 JDBC 表是一种可以提高性能的优化技术。要详细了解确定何时适合使用这种技术的过程，请参阅《AWS 规范性指南》中“优化 AWS Glue for Apache Spark 作业性能的最佳实践”**指南中的 [减少数据扫描量](https://docs.aws.amazon.com/prescriptive-guidance/latest/tuning-aws-glue-for-apache-spark/parallelize-tasks.html)。

要启用并行读取，可在表结构的参数字段中设置键值对。使用 JSON 表示法为表的参数字段设置值。有关编辑表属性的更多信息，请参阅 [查看和管理表详细信息](tables-described.md#console-tables-details)。当您调用 ETL（提取、转换和加载）方法 `create_dynamic_frame_from_options` 和 `create_dynamic_frame_from_catalog` 时，您也可以启用并行读取。有关在这些方法中指定选项的更多信息，请参阅 [from\$1options](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader-from_options) 和 [from\$1catalog](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader-from_catalog)。

您可以将此方法用于 JDBC 表，也即，其基本数据是 JDBC 数据存储的大多数表。当读取 Amazon Redshift 和 Amazon S3 表时，这些属性将被忽略。

**hashfield**  
将 `hashfield` 设置为 JDBC 表中要用来将数据划分成分区的列的名称。为了获得最佳效果，此列应具有值的偶数分布以便在各分区之间分布数据。此列可以是任意数据类型。AWS Glue 生成非重叠的查询，这些查询并行运行以读取通过此列进行分区的数据。例如，如果您的数据按月份均匀地分布，您可以使用 `month` 列并行读取每月的数据。  

```
  'hashfield': 'month'
```
AWS Glue 创建一个查询以便将字段值哈希处理成分区编号，并针对这些分区并行运行该查询。要使用您自己的查询对表读取进行分区，请提供 `hashexpression` 而不是 `hashfield`。

**hashexpression**  
将 `hashexpression` 设置为会返回一个整数的 SQL 表达式（符合 JDBC 数据库引擎语法）。简单表达式是表中任何数字列的名称。AWS Glue 生成 SQL 查询以并行读取 JDBC 数据（通过使用 `WHERE` 子句中的 `hashexpression` 对数据分区）。  
例如，使用数字列 `customerID` 来读取按客户编号分区的数据。  

```
  'hashexpression': 'customerID'
```
要让 AWS Glue 控制分区，请提供 `hashfield` 而不是 `hashexpression`。

**hashpartitions**  
将 `hashpartitions` 设置为 JDBC 表的并行读取数目。如果未设置该属性，默认值为 7。  
例如，将并行读取数目设置为 `5`，以便 AWS Glue 通过五个（或更少）查询读取您的数据。  

```
  'hashpartitions': '5'
```

# 设置 Amazon VPC 以建立从 AWS Glue 到 Amazon RDS 数据存储的 JDBC 连接
<a name="setup-vpc-for-glue-access"></a>

 使用 JDBC 连接到 Amazon RDS 中的数据库时，您需要执行额外的设置。要允许 AWS Glue 组件与 Amazon RDS 进行通信，您必须在 Amazon VPC 中设置对 Amazon RDS 数据存储的访问权限。要支持 AWS Glue 在其组件之间通信，请为所有 TCP 端口指定一个具有自引用入站规则的安全组。通过创建自引用规则，您可以将源限制为 VPC 中的同一安全组。自引用规则不会向所有网络开放 VPC。VPC 的默认安全组可能已经为所有流量设置了自引用入站规则。

**设置 AWS Glue 和 Amazon RDS 数据存储之间的访问权限**

1. 登录 AWS 管理控制台 并通过以下网址打开 Amazon RDS 控制台：[https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)。

1. 在 Amazon RDS 控制台中，找到用于控制 Amazon RDS 数据库访问权限的安全组。

   在左侧导航窗格中，选择**数据库**，然后从主窗格的列表中选择要连接的实例。

   在数据库详细信息页面中，在**连接和安全**选项卡上找到 **VPC 安全组**。

1. 根据您的网络架构，确定最适合修改以允许 Glue AWS 服务访问的关联安全组。保存其名称 *database-security-group*，以备将来参考。如果没有合适的安全组，请按照 Amazon RDS 文档中[通过创建安全组提供对 VPC 中的数据库实例的访问](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_SettingUp.html)部分的说明操作。

1. 登录到 AWS 管理控制台并打开 Amazon VPC 控制台，网址：[https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/)。

1. 在 Amazon VPC 控制台中，确定如何更新 *database-security-group*。

   在左侧导航窗格中，选择**安全组**，然后从主窗格的列表中选择 *database-security-group*。

1. 找到 *database-security-group* 的安全组 ID，即 *database-sg-id*。保存以备将来参考。

   在安全组详细信息页面中，找到**安全组 ID**。

1. 更改 *database-security-group* 的入站规则，添加自引用规则以允许 AWS Glue 组件进行通信。具体来讲，添加或确认有一条**类型**为 `All TCP`，**协议**为 `TCP`，**端口范围**包括所有端口，且**源**为 *database-sg-id* 的规则。确认您为**源**输入的安全组正是您正在编辑的安全组。

   在安全组详细信息页面中，选择**编辑入站规则**。

   入站规则类似于以下内容：  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/setup-vpc-for-glue-access.html)

1. 添加出站流量规则。

   在安全组详细信息页面中，选择**编辑出站规则**。

   如果您的安全组允许所有出站流量，则不需要单独的规则。例如：  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/setup-vpc-for-glue-access.html)

   如果您的网络架构旨在限制出站流量，请创建以下出站规则：

   创建**类型**为 `All TCP`，**协议**为 `TCP`，**端口范围**包括所有端口，且**目标**为 *database-sg-id* 的自引用规则。确认您为**目标**输入的安全组正是您正在编辑的安全组。

    如果使用 Amazon S3 VPC 端点，添加 HTTPS 规则以允许从该 VPC 到 Amazon S3 的流量。创建一条**类型**为 `HTTPS`，**协议**为 `TCP`，**端口范围**为 `443`，**目标**为 Amazon S3 网关端点的托管前缀列表 ID（即 *s3-prefix-list-id*）的规则。有关前缀列表和 Amazon S3 网关端点的更多信息，请参阅 Amazon VPC 文档中的 [Amazon S3 网关端点](https://docs.aws.amazon.com//vpc/latest/privatelink/vpc-endpoints-s3.html)。

   例如：  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/setup-vpc-for-glue-access.html)

# MongoDB 连接
<a name="aws-glue-programming-etl-connect-mongodb-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 来读取和写入 MongoDB 和 MongoDB Atlas 中的表。您可以通过 AWS Glue 连接并使用存储在 AWS Secrets Manager 中的用户名和密码凭证连接到 MongoDB。

有关 MongoDB 的更多信息，请参阅 [MongoDB 文档](https://www.mongodb.com/docs/)。

## 配置 MongoDB 连接
<a name="aws-glue-programming-etl-connect-mongodb-configure"></a>

要从 AWS Glue 连接到 MongoDB，您需要拥有 MongoDB 凭证 *mongodbUser* 和 *mongodbPass*。

要从 AWS Glue 连接到 MongoDB，您可能需要满足一些先决条件：
+ 如果您的 MongoDB 实例位于某个 Amazon VPC 中，请确保您的 Amazon VPC 配置允许您的 AWS Glue 作业与 MongoDB 实例进行通信，并且无需通过公共互联网路由流量。

  在 Amazon VPC 中，确定或创建将在执行 AWS Glue 作业时使用的 **VPC**、**子网**和**安全组**。此外，您的 Amazon VPC 配置需要允许您的 MongoDB 实例与该位置之间的网络流量。根据您的网络布局，这可能需要更改安全组规则、网络 ACL、NAT 网关和对等连接。

然后您可以继续配置 AWS Glue 以便与 MongoDB 配合使用。

**配置 MongoDB 连接：**

1. 您还可以在 AWS Secrets Manager 中使用您的 MongoDB 凭证创建密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `username` 和值 *mongodbUser* 创建一个键值对。

     在选择**键/值对**时，请使用键 `password` 和值 *mongodbPass* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名为 *connectionName*，以供未来在 AWS Glue 中使用。
   + 选择**连接类型**时，请选择 **MongoDB** 或 **MongoDB Atlas**。
   + 选择 **MongoDB URL** 或 **MongoDB Atlas URL** 时，请提供 MongoDB 实例的主机名。

     MongoDB URL 的格式为 `mongodb://mongoHost:mongoPort/mongoDBname`。

     MongoDB Atlas URL 的格式为 `mongodb+srv://mongoHost/mongoDBname`。
   + 如果您选择创建 Secrets Manager 密钥，请选择 AWS Secrets Manager **凭证类型**。

     然后在 **AWS密钥**中提供 *secretName*。
   + *如果您选择提供**用户名和密码**，请提供 *mongodbUser* 和 mongodbPass*。

1. 对于下列情况，您可能需要添加额外的配置：
   + 

     对于通过 Amazon VPC 在 AWS 云端托管的 MongoDB 实例
     + 您需要向 AWS Glue 连接提供用于定义 MongoDB 安全凭证的 Amazon VPC 连接信息。创建或更新连接时，请在**网络选项**中设置 **VPC**、**子网**和**安全组**。

创建 AWS Glue MongoDB 连接后，您需要执行以下操作，然后才能调用您的连接方法：
+ 如果您选择创建 Secrets Manager 密钥，请向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

要在 AWS Glue for Spark 中使用 AWS Glue MongoDB 连接，请在您连接方法调用中提供 `connectionName` 选项。您还可以按照 [在 ETL 作业中使用 MongoDB 连接](integrate-with-mongo-db.md) 中的步骤操作，将该连接与 AWS Glue Data Catalog 结合使用。

## 使用 AWS Glue 连接从 MongoDB 读取
<a name="aws-glue-programming-etl-connect-mongodb-read"></a>

**先决条件：**
+ 您要读取的 MongoDB 集合。您将需要该集合的标识信息。

  MongoDB 集合由数据库名 *mongodbName* 和集合名 *mongodbCollection* 来标识。
+ 为了提供身份验证信息而配置的 AWS Glue MongoDB 连接。完成上一节“配置 MongoDB 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
mongodb_read = glueContext.create_dynamic_frame.from_options(
    connection_type="mongodb",
    connection_options={
        "connectionName": "connectionName",
        "database": "mongodbName",
        "collection": "mongodbCollection",
        "partitioner": "com.mongodb.spark.sql.connector.read.partitioner.SinglePartitionPartitioner",
        "partitionerOptions.partitionSizeMB": "10",
        "partitionerOptions.partitionKey": "_id",
        "disableUpdateUri": "false",
    }
)
```

## 写入 MongoDB 表
<a name="aws-glue-programming-etl-connect-mongodb-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 MongoDB。

**先决条件：**
+ 您要写入的 MongoDB 集合。您将需要该集合的标识信息。

  MongoDB 集合由数据库名 *mongodbName* 和集合名 *mongodbCollection* 来标识。
+ 为了提供身份验证信息而配置的 AWS Glue MongoDB 连接。完成上一节“配置 MongoDB 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="mongodb",
    connection_options={
        "connectionName": "connectionName",
        "database": "mongodbName",
        "collection": "mongodbCollection",
        "disableUpdateUri": "false",
        "retryWrites": "false", 
    },
)
```

## 读取和写入 MongoDB 表
<a name="aws-glue-programming-etl-connect-mongodb-read-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 MongoDB。

**先决条件：**
+ 您要读取的 MongoDB 集合。您将需要该集合的标识信息。

  您要写入的 MongoDB 集合。您将需要该集合的标识信息。

  MongoDB 集合由数据库名 *mongodbName* 和集合名 *mongodbCollection* 来标识。
+ MongoDB 身份验证信息 *mongodbUser* 和 *mongodbPassword*。

例如：

------
#### [ Python ]

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext, SparkConf
from awsglue.context import GlueContext
from awsglue.job import Job
import time

## @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

job = Job(glueContext)
job.init(args['JOB_NAME'], args)

output_path = "s3://some_bucket/output/" + str(time.time()) + "/"
mongo_uri = "mongodb://<mongo-instanced-ip-address>:27017"
mongo_ssl_uri = "mongodb://<mongo-instanced-ip-address>:27017"
write_uri = "mongodb://<mongo-instanced-ip-address>:27017"

read_mongo_options = {
    "uri": mongo_uri,
    "database": "mongodbName",
    "collection": "mongodbCollection",
    "username": "mongodbUsername",
    "password": "mongodbPassword",
    "partitioner": "MongoSamplePartitioner",
    "partitionerOptions.partitionSizeMB": "10",
    "partitionerOptions.partitionKey": "_id"}

ssl_mongo_options = {
    "uri": mongo_ssl_uri,
    "database": "mongodbName",
    "collection": "mongodbCollection",
    "ssl": "true",
    "ssl.domain_match": "false"
}

write_mongo_options = {
    "uri": write_uri,
    "database": "mongodbName",
    "collection": "mongodbCollection",
    "username": "mongodbUsername",
    "password": "mongodbPassword",
}

# Get DynamicFrame from MongoDB
dynamic_frame = glueContext.create_dynamic_frame.from_options(connection_type="mongodb",
                                                              connection_options=read_mongo_options)

# Write DynamicFrame to MongoDB
glueContext.write_dynamic_frame.from_options(dynamicFrame, connection_type="mongodb", connection_options=write_mongo_options)

job.commit()
```

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

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._

object GlueApp {
  val DEFAULT_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  val WRITE_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  lazy val defaultJsonOption = jsonOptions(DEFAULT_URI)
  lazy val writeJsonOption = jsonOptions(WRITE_URI)
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    // Get DynamicFrame from MongoDB
    val dynamicFrame: DynamicFrame = glueContext.getSource("mongodb", defaultJsonOption).getDynamicFrame()

    // Write DynamicFrame to MongoDB
    glueContext.getSink("mongodb", writeJsonOption).writeDynamicFrame(dynamicFrame)

    Job.commit()
  }

  private def jsonOptions(uri: String): JsonOptions = {
    new JsonOptions(
      s"""{"uri": "${uri}",
         |"database":"mongodbName",
         |"collection":"mongodbCollection",
         |"username": "mongodbUsername",
         |"password": "mongodbPassword",
         |"ssl":"true",
         |"ssl.domain_match":"false",
         |"partitioner": "MongoSamplePartitioner",
         |"partitionerOptions.partitionSizeMB": "10",
         |"partitionerOptions.partitionKey": "_id"}""".stripMargin)
  }
}
```

------

## MongoDB 连接选项参考
<a name="aws-glue-programming-etl-connect-mongodb"></a>

指定与 MongoDB 的连接。源连接和接收器连接的连接选项不同。

源连接和接收器连接之间会共享以下连接属性：
+ `connectionName` - 用于读/写。为了向您的连接方法提供身份验证和网络信息而配置的 AWS Glue MongoDB 连接的名称。如果在按照上一节“[配置 MongoDB 连接](#aws-glue-programming-etl-connect-mongodb-configure)”所述配置 AWS Glue 连接时提供 `connectionName`，则不再需要提供 `"uri"`、`"username"` 和 `"password"` 连接选项。
+ `"uri"`：（必需）要从中读取数据的 MongoDB 主机，格式为 `mongodb://<host>:<port>`。适用于 AWS Glue 4.0 之前的 AWS Glue 版本。
+ `"connection.uri"`：（必需）要从中读取数据的 MongoDB 主机，格式为 `mongodb://<host>:<port>`。适用于 AWS Glue 4.0 及更高版本。
+ `"username"`：（必需）MongoDB 用户名。
+ `"password"`：（必需）MongoDB 密码。
+ `"database"`：（必需）要从中读取数据的 MongoDB 数据库。当在您的任务脚本中调用 `glue_context.create_dynamic_frame_from_catalog` 时，此选项还可以在 `additional_options` 中传递。
+ `"collection"`：（必需）要从中读取数据的 MongoDB 集合。当在您的任务脚本中调用 `glue_context.create_dynamic_frame_from_catalog` 时，此选项还可以在 `additional_options` 中传递。

### "connectionType": "mongodb" as Source
<a name="etl-connect-mongodb-as-source"></a>

将 `"connectionType": "mongodb"` 用作源时可使用以下连接选项：
+ `"ssl"`：（可选）如果为 `true`，则启动 SSL 连接。默认值为 `false`。
+ `"ssl.domain_match"`：（可选）如果为 `true`，且 `ssl` 为 `true`，则执行域匹配检查。默认值为 `true`。
+ `"batchSize"`：（可选）每个批处理返回的文档数量，在内部批处理的游标中使用。
+ `"partitioner"`：（可选）从 MongoDB 中读取输入数据的分区器的类名称。该连接器提供以下分区器：
  + `MongoDefaultPartitioner`（默认）（AWS Glue 4.0 不支持）
  + `MongoSamplePartitioner`（需要 MongoDB 3.2 或更高版本）（但 AWS Glue 4.0 不支持）
  + `MongoShardedPartitioner`（AWS Glue 4.0 不支持）
  + `MongoSplitVectorPartitioner`（AWS Glue 4.0 不支持）
  + `MongoPaginateByCountPartitioner`（AWS Glue 4.0 不支持）
  + `MongoPaginateBySizePartitioner`（AWS Glue 4.0 不支持）
  + `com.mongodb.spark.sql.connector.read.partitioner.SinglePartitionPartitioner`
  + `com.mongodb.spark.sql.connector.read.partitioner.ShardedPartitioner`
  + `com.mongodb.spark.sql.connector.read.partitioner.PaginateIntoPartitionsPartitioner`
+ `"partitionerOptions"`：（可选）指定分区器的选项。各个分区器支持的选项如下：
  + `MongoSamplePartitioner`: `partitionKey`, `partitionSizeMB`, `samplesPerPartition`
  + `MongoShardedPartitioner`: `shardkey`
  + `MongoSplitVectorPartitioner`: `partitionKey`, `partitionSizeMB`
  + `MongoPaginateByCountPartitioner`: `partitionKey`, `numberOfPartitions`
  + `MongoPaginateBySizePartitioner`: `partitionKey`, `partitionSizeMB`

  有关这些选项的更多信息，请参阅 MongoDB 文档中的[分区器配置](https://docs.mongodb.com/spark-connector/master/configuration/#partitioner-conf)。

### "connectionType": "mongodb" as Sink
<a name="etl-connect-mongodb-as-sink"></a>

将 `"connectionType": "mongodb"` 用作连接器时可使用以下连接选项：
+ `"ssl"`：（可选）如果为 `true`，则启动 SSL 连接。默认值为 `false`。
+ `"ssl.domain_match"`：（可选）如果为 `true`，且 `ssl` 为 `true`，则执行域匹配检查。默认值为 `true`。
+ `"extendedBsonTypes"`：（可选）如果为 `true`，则在 MongoDB 中写入数据时会允许扩展 BSON 类型。默认值为 `true`。
+ `"replaceDocument"`：（可选）如果为 `true`，则在保存包含 `_id` 字段的数据集时会替换整个文档。如果为 `false`，则只会更新文档中与数据集中的字段匹配的字段。默认值为 `true`。
+ `"maxBatchSize"`：（可选）保存数据时的批量操作的最大批次大小。默认值为 512。
+ `"retryWrites"`：（可选）：如果 AWS Glue 遇到网络错误，则会自动重试某些写入操作一次。

# SAP HANA 连接
<a name="aws-glue-programming-etl-connect-saphana-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 来读取和写入 SAP HANA 中的表。您可以使用 SQL 查询来定义要从 SAP HANA 中读取的信息。您可以通过 AWS Glue SAP HANA 连接并使用存储在 AWS Secrets Manager 中的 JDBC 凭证连接到 SAP HANA。

有关 SAP HANA JDBC 的更多信息，请参阅 [SAP HANA 文档](https://help.sap.com/docs/SAP_HANA_PLATFORM/0eec0d68141541d1b07893a39944924e/ff15928cf5594d78b841fbbe649f04b4.html)。

## 配置 SAP HANA 连接
<a name="aws-glue-programming-etl-connect-saphana-configure"></a>

要从 AWS Glue 连接到 SAP HANA，您需要创建 SAP HANA 凭证并将其存储在某个 AWS Secrets Manager 密钥中，然后将该密钥关联到某个 SAP HANA AWS Glue 连接。您需要配置 SAP HANA 服务与 AWS Glue 之间的网络连接。

要连接到 SAP HANA，您可能需要满足一些先决条件：
+ 如果您的 SAP HANA 服务位于某个 Amazon VPC 中，请确保您的 Amazon VPC 配置允许您的 AWS Glue 作业与 SAP HANA 服务进行通信，并且无需通过公共互联网路由流量。

  在 Amazon VPC 中，确定或创建将在执行 AWS Glue 作业时使用的 **VPC**、**子网**和**安全组**。此外，您的 Amazon VPC 配置需要允许您的 SAP HANA 端点与该位置之间的网络流量。您的作业需要与您的 SAP HANA JDBC 端口建立 TCP 连接。有关 SAP HANA 端口的更多信息，请参阅 [SAP HANA 文档](https://help.sap.com/docs/HANA_SMART_DATA_INTEGRATION/7952ef28a6914997abc01745fef1b607/88e2e8bded9e4041ad3ad87dc46c7b55.html?locale=en-US)。根据您的网络布局，这可能需要更改安全组规则、网络 ACL、NAT 网关和对等连接。
+ 如果您的 SAP HANA 端点可以访问互联网，则无需满足其他先决条件。

**配置 SAP HANA 连接：**

1. 在 AWS Secrets Manager 中，使用您的 SAP HANA 凭证创建一个密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `username/USERNAME` 和值 *saphanaUsername* 创建一个键值对。
   + 在选择**键/值对**时，请使用键 `password/PASSWORD` 和值 *saphanaPassword* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名为 *connectionName*，以供未来在 AWS Glue 中使用。
   + 选择**连接类型**时，请选择 SAP HANA。
   + 在提供 **SAP HANA URL** 时，请提供您的实例的 URL。

     SAP HANA JDBC URL 的格式为 `jdbc:sap://saphanaHostname:saphanaPort/?databaseName=saphanaDBname,ParameterName=ParameterValue`

     AWS Glue 需要以下 JDBC URL 参数：
     + `databaseName` – SAP HANA 中要连接的默认数据库。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

创建 AWS Glue SAP HANA 连接后，您需要完成以下操作，然后才能运行 AWS Glue 作业：
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 读取 SAP HANA 表
<a name="aws-glue-programming-etl-connect-saphana-read"></a>

**先决条件** 
+ 您要读取的 SAP HANA 表。您将需要该表的标识信息。

  可以使用 SAP HANA 表名和 Schema 名（格式为 `schemaName.tableName`）来指定表。如果表的 Schema 为默认的“public”，则不需要指定 Schema 名和“.”分隔符。调用此 *tableIdentifier* 操作。请注意，数据库在 `connectionName` 中是以 JDBC URL 参数的形式提供的。
+ 为了提供身份验证信息而配置的 AWS Glue SAP HANA 连接。完成上一节“配置 SAP HANA 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
saphana_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type="saphana",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableIdentifier",
    }
)
```

您还可以提供 SELECT SQL 查询来筛选返回到 DynamicFrame 的结果。您将需要配置 `query`。

例如：

```
saphana_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="saphana",
    connection_options={
        "connectionName": "connectionName",
        "query": "query"
    }
)
```

## 写入 SAP HANA 表
<a name="aws-glue-programming-etl-connect-saphana-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 SAP HANA。如果表中已经含有信息，则 AWS Glue 会出现错误。

**先决条件** 
+ 您要写入的 SAP HANA 表。

  可以使用 SAP HANA 表名和 Schema 名（格式为 `schemaName.tableName`）来指定表。如果表的 Schema 为默认的“public”，则不需要指定 Schema 名和“.”分隔符。调用此 *tableIdentifier* 操作。请注意，数据库在 `connectionName` 中是以 JDBC URL 参数的形式提供的。
+ SAP HANA 身份验证信息。完成上一节“配置 SAP HANA 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
options = {
    "connectionName": "connectionName",
    "dbtable": 'tableIdentifier'
}

    saphana_write = glueContext.write_dynamic_frame.from_options(
        frame=dynamicFrame,
        connection_type="saphana",
        connection_options=options
)
```

## SAP HANA 连接选项参考
<a name="aws-glue-programming-etl-connect-saphana-reference"></a>
+ `connectionName` – 必需。用于读/写。为了向您的连接方法提供身份验证和网络信息而配置的 AWS Glue SAP HANA 连接的名称。
+ `databaseName` - 用于读/写。有效值：SAP HANA 中数据库的名称。要连接的数据库的名称。
+ `dbtable` – 对于写入为必填项，对于读取也为必填项，但提供了 `query` 时除外。用于读/写。有效值：SAP HANA SQL FROM 子句的内容。标识要连接的 SAP HANA 中的表。除表名之外，您还可以提供其他 SQL，例如子查询。有关更多信息，请参阅 SAP HANA 文档中的 [From clause](https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/20fcf24075191014a89e9dc7b8408b26.html#loio20fcf24075191014a89e9dc7b8408b26__from_clause)。
+ `query` – 用于读取。用来定义从 SAP HANA 读取数据时要检索的内容的 SAP HANA SQL SELECT 查询。

# Snowflake 连接
<a name="aws-glue-programming-etl-connect-snowflake-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 在 Snowflake 中读取和写入表。您可以通过 SQL 查询从 Snowflake 中读取。您可以使用用户名和密码连接到 Snowflake。您可以通过 AWS Glue Data Catalog 引用存储在 AWS Secrets Manager 中的 Snowflake 凭证。用于 AWS Glue for Spark 的 Data Catalog Snowflake 凭证与用于爬网程序的 Data Catalog Snowflake 凭证分开存储。必须选择 `SNOWFLAKE` 类型连接，而不是配置为连接到 Snowflake 的 `JDBC` 类型连接。

有关 Snowflake 的更多信息，请参阅 [Snowflake 网站](https://www.snowflake.com/)。有关 AWS 上 Snowflake 的更多信息，请参阅 [Snowflake Data Warehouse on Amazon Web Services](https://aws.amazon.com/financial-services/partner-solutions/snowflake/)。

## 配置 Snowflake 连接
<a name="aws-glue-programming-etl-connect-snowflake-configure"></a>

连接到可通过互联网访问的 Snowflake 数据库没有任何 AWS 先决条件。

或者，您可以执行以下配置，使用 AWS Glue 管理连接凭证。

**使用 AWS Glue 管理连接凭证**

1. 在 Snowflake 中，生成一个用户 *snowflakeUser* 和密码 *snowflakePassword*。

1. 在 AWS Secrets Manager 中，使用您的 Snowflake 凭证创建密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html#create_secret_cli)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 选择**键/值对**时，请使用键 `USERNAME` 为 *snowflakeUser* 创建一对。
   + 选择**键/值对**时，请使用键 `PASSWORD` 为 *snowflakePassword* 创建一对。
   + 选择**键/值对**时，您可以向 Snowflake 仓库提供键 `sfWarehouse`。
   + 选择**键/值对**时，您可以将对应的 Spark 属性名称作为键，从而提供其他 Snowflake 连接属性。支持的属性包括：
     + `sfDatabase`：Snowflake 数据库名称
     + `sfSchema`：Snowflake 架构名称
     + `sfRole`：Snowflake 角色名称
     + `pem_private_key`：用于密钥对身份验证的私有密钥

1. 在 AWS Glue Data Catalog 中，通过选择**连接**，然后选择**创建连接**来创建连接。按照连接向导中的步骤完成该过程：
   + 选择**数据来源**时，选择 Snowflake，然后选择**下一步**。
   + 输入连接详细信息，例如主机和端口。输入主机 **Snowflake URL** 时，请提供您的 Snowflake 实例的 URL。URL 通常将使用表单 `account_identifier.snowflakecomputing.com` 中的主机名。但是，URL 格式可能会有所不同，具体取决于您的 Snowflake 帐户类型（例如，AWS、Azure 或 Snowflake 托管）。
   + 选择 IAM 服务角色时，从下拉菜单中选择。这是账户中的 IAM 角色，如果指定了 VPC，则该角色将用于访问 AWS Secrets Manager 和分配 IP。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

1. 在向导的下一步中，设置 Snowflake 连接的属性。

1. 在向导的最后一步中，查看您的设置，然后完成创建连接的过程。

在以下情况下，您可能需要以下内容：
+ 

  适用于托管在 AWS 中 Amazon VPC 上的 Snowflake
  + 您需要对 Snowflake 进行适当的 Amazon VPC 配置。有关如何配置 Amazon VPC 的更多信息，请参阅 Snowflake 文档中的 [AWS PrivateLink & Snowflake](https://docs.snowflake.com/en/user-guide/admin-security-privatelink)。
  + 您需要对 AWS Glue 进行适当的 Amazon VPC 配置。[为 AWS Glue（AWS PrivateLink）配置接口 VPC 端点（AWS PrivateLink）](vpc-interface-endpoints.md)
  + 您需要创建一个提供 Amazon VPC 连接信息的 AWS Glue Data Catalog 连接（以及定义您的 Snowflake 安全凭证的 AWS Secrets Manager 密钥 ID）。使用 AWS PrivateLink 时您的 URL 将发生变化，如前一项目中链接的 Snowflake 文档中所述。
  + 您需要在作业配置中将 Data Catalog 连接作为**附加网络连接**包括在内。

## 从 Snowflake 表中读取
<a name="aws-glue-programming-etl-connect-snowflake-read"></a>

**先决条件：**您想读取的 Snowflake 表。您需要使用 Snowflake 表名 *tableName*。您需要 Snowflake url *snowflakeUrl*、用户名 *snowflakeUser* 和密码 *snowflakePassword*。如果您的 Snowflake 用户没有设置默认命名空间，则需要 Snowflake 数据库名称 *databaseName* 和架构名称 *schemaName*。此外，如果您的 Snowflake 用户没有设置默认仓库，则需要仓库名称 *warehouseName*。

例如：

**其他先决条件：**完成*使用 AWS Glue 管理连接凭证*的步骤，配置 *snowflakeUrl*、*snowflakeUsername* 和 *snowflakePassword*。要查看这些步骤，请参阅 [配置 Snowflake 连接](#aws-glue-programming-etl-connect-snowflake-configure) 上一节。为选择要连接的**附加网络连接**，我们将使用 `connectionName` 参数。

```
snowflake_read = glueContext.create_dynamic_frame.from_options(
  connection_type="snowflake",
  connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName",
        "sfDatabase": "databaseName",
        "sfSchema": "schemaName",
        "sfWarehouse": "warehouseName",
    }
)
```

 此外，您还可以使用 `autopushdown` 和 `query` 参数来读取 Snowflake 表的一部分。这可能比在结果加载到 Spark 后对其进行筛选要有效得多。举一个例子，其中所有销售额都存储在同一个表中，但您只需要分析假日期间某家商店的销售额即可。如果这些信息存储在表中，则可以使用谓词下推来检索结果，如下所示：

```
snowflake_node = glueContext.create_dynamic_frame.from_options(
    connection_type="snowflake",
    connection_options={
        "autopushdown": "on",
        "query": "select * from sales where store='1' and IsHoliday='TRUE'",
        "connectionName": "snowflake-glue-conn",
        "sfDatabase": "databaseName",
        "sfSchema": "schemaName",
        "sfWarehouse": "warehouseName",
    }
)
```

## 写入 Snowflake 表
<a name="aws-glue-programming-etl-connect-snowflake-write"></a>

**先决条件：**您要写入的 Snowflake 数据库。您将需要一个最新或所需的表名，如 *tableName*。您需要 Snowflake url *snowflakeUrl*、用户名 *snowflakeUser* 和密码 *snowflakePassword*。如果您的 Snowflake 用户没有设置默认命名空间，则需要 Snowflake 数据库名称 *databaseName* 和架构名称 *schemaName*。此外，如果您的 Snowflake 用户没有设置默认仓库，则需要仓库名称 *warehouseName*。

例如：

**其他先决条件：**完成*使用 AWS Glue 管理连接凭证*的步骤，配置 *snowflakeUrl*、*snowflakeUsername* 和 *snowflakePassword*。要查看这些步骤，请参阅 [配置 Snowflake 连接](#aws-glue-programming-etl-connect-snowflake-configure) 上一节。为选择要连接的**附加网络连接**，我们将使用 `connectionName` 参数。

```
glueContext.write_dynamic_frame.from_options(
    connection_type="snowflake",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName",
        "sfDatabase": "databaseName",
        "sfSchema": "schemaName",
        "sfWarehouse": "warehouseName",
    },
)
```

## Snowflake 连接选项参考
<a name="aws-glue-programming-etl-connect-snowflake-reference"></a>

Snowflake 连接类型采用以下连接选项：

您可以从 Data Catalog 连接（`sfUrl`、`sfUser`、`sfPassword`）中检索本节中的某些参数，在这种情况下，您无需提供这些参数。您可以提供参数 `connectionName` 来实现。

您可以使用 `secretId` 参数检索 AWS Secrets Manager 密钥中的连接参数。如果您使用 Secrets Manager 并且密钥中存在以下 Spark 属性，则系统会自动检索这些属性：
+ `sfUser`（使用密钥 `USERNAME` 或 `sfUser`）
+ `sfPassword`（使用密钥 `PASSWORD` 或 `sfPassword`）
+ `sfWarehouse`（使用密钥 `sfWarehouse`）
+ `sfDatabase`（使用密钥 `sfDatabase`）
+ `sfSchema`（使用密钥 `sfSchema`）
+ `sfRole`（使用密钥 `sfRole`）
+ `pem_private_key`（使用密钥 `pem_private_key`）

**属性优先顺序：**在多个位置指定了相同属性时，AWS Glue 将按以下优先顺序（从高到低）处理：

1. 作业代码中显式提供的连接选项

1. Data Catalog 连接属性

1. AWS Secrets Manager 密钥值（指定 `secretId` 时）

1. Snowflake 用户默认值

连接到 Snowflake 时通常使用以下参数。
+ `sfDatabase` - 如果未在 Snowflake 中设置用户默认值，则为必填项。用于读/写。连接后用于会话的数据库。
+ `sfSchema` - 如果未在 Snowflake 中设置用户默认值，则为必填项。用于读/写。连接后用于会话的架构。
+ `sfWarehouse` - 如果未在 Snowflake 中设置用户默认值，则为必填项。用于读/写。连接后用于会话的默认虚拟仓库。
+ `sfRole` - 如果未在 Snowflake 中设置用户默认值，则为必填项。用于读/写。连接后用于会话的默认安全角色。
+ `sfUrl` -（必需）用于读/写。采用以下格式指定账户的主机名：`account_identifier.snowflakecomputing.com`。有关账户标识符的更多信息，请参阅 Snowflake 文档中的 [Account Identifiers](https://docs.snowflake.com/en/user-guide/admin-account-identifier)。
+ `sfUser` -（必需）用于读/写。Snowflake 用户的登录名。
+ `sfPassword` —（除非提供 `pem_private_key`，否则为必填项）用于读/写。Snowflake 用户的密码。
+ `dbtable` - 处理完整表格时为必填项。用于读/写。要读取的表的名称或要写入数据的表的名称。读取时，将检索所有列和记录。
+ `pem_private_key` - 用于读/写。未加密的 b64 编码私钥字符串。Snowflake 用户的私钥。通常将其从 PEM 文件中复制出来。有关更多信息，请参阅 Snowflake 文档中的[密钥对身份验证和密钥对轮换](https://docs.snowflake.com/en/user-guide/key-pair-auth)。
+ `query` - 使用查询读取时为必填项。用于读取。要运行的确切查询（`SELECT` 语句）

以下选项用于配置连接到 Snowflake 过程中的特定行为。
+ `preactions` - 用于读/写。有效值：以分号分隔的 SQL 语句列表作为字符串。SQL 语句在 AWS Glue 和 Snowflake 之间传输数据之前运行。如果语句包含 `%s`，则 `%s` 将替换为操作所引用的表名。
+ `postactions` - 用于读/写。SQL 语句在 AWS Glue 和 Snowflake 之间传输数据之后运行。如果语句包含 `%s`，则 `%s` 将替换为操作所引用的表名。
+ `autopushdown` - 默认值：`"on"`。有效值：`"on"`、`"off"`。此参数控制是否启用自动查询下推。如果启用了下推，那么当在 Spark 上运行查询时，如果可以将部分查询“下推”到 Snowflake 服务器，则会将其下推。这提高了某些查询的性能。有关是否可以下推查询的信息，请参阅 Snowflake 文档中的 [Pushdown](https://docs.snowflake.com/en/user-guide/spark-connector-use#pushdown)。

此外，AWS Glue 可能支持 Snowflake Spark 连接器上可用的某些选项。有关 Snowflake Spark 连接器上可用选项的更多信息，请参阅 Snowflake 文档中的 [Setting Configuration Options for the Connector](https://docs.snowflake.com/en/user-guide/spark-connector-use#setting-configuration-options-for-the-connector)。

## Snowflake 身份验证方法
<a name="aws-glue-programming-etl-connect-snowflake-authentication"></a>

AWS Glue 支持使用以下身份验证方法连接到 Snowflake：
+ **用户名和密码身份验证：**提供 `sfUser` 和 `sfPassword` 参数。
+ **密钥对身份验证：**提供 `sfUser` 和 `pem_private_key` 参数。使用密钥对身份验证方法时，`sfPassword` 参数不是必需的。

这两种身份验证方法都完全受支持，并且可以使用任意连接选项、Data Catalog 连接或 AWS Secrets Manager 密钥组合进行配置。

## Snowflake 连接器限制
<a name="aws-glue-programming-etl-connect-snowflake-limitations"></a>

使用 AWS Glue for Spark 连接到 Snowflake 需要遵守以下限制。
+ 此连接器不支持作业书签。有关作业书签的更多信息，请参阅 [使用作业书签跟踪已处理的数据](monitor-continuations.md)。
+ 此连接器不支持 Snowflake 使用 `create_dynamic_frame.from_catalog` 和 `write_dynamic_frame.from_catalog` 方法对 AWS Glue Data Catalog 中的表进行读取和写入。
+ 此连接器支持用户名/密码身份验证和密钥对身份验证方法。目前不支持其他身份验证方法（例如 OAuth 或 SAML）。
+ 流作业中不支持此连接器。
+ 此连接器在检索信息（例如使用 `query` 参数）时支持基于 `SELECT` 语句的查询。不支持其他类型的查询（例如 `SHOW`、`DESC` 或 DML 语句）。
+ Snowflake 将通过 Snowflake 客户端提交的查询文本（即 SQL 语句）的大小限制为每条语句 1MB。有关更多详细信息，请参阅 [Limits on Query Text Size](https://docs.snowflake.com/en/user-guide/query-size-limits)。

# Teradata Vantage 连接
<a name="aws-glue-programming-etl-connect-teradata-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 来读取和写入 Teradata Vantage 中的表。您可以使用 SQL 查询来定义要从 Teradata 中读取的信息。您可以通过 AWS Glue 连接并使用存储在 AWS Secrets Manager 中的用户名和密码凭证连接到 Teradata。

有关 Teradata 的更多信息，请参阅 [Teradata 文档](https://docs.teradata.com/)

## 配置 Teradata 连接
<a name="aws-glue-programming-etl-connect-teradata-configure"></a>

要从 AWS Glue 连接到 Teradata，您需要创建 Teradata 凭证并将其存储在某个 AWS Secrets Manager 密钥中，然后将该密钥关联到某个 AWS Glue Teradata 连接。如果您的 Teradata 实例位于某个 Amazon VPC 中，则还需要提供 AWS Glue Teradata 连接的联网选项。

要从 AWS Glue 连接到 Teradata，您可能需要满足一些先决条件：
+ 如果您通过 Amazon VPC 访问您的 Teradata 环境，您的 Amazon VPC 配置应允许您的 AWS Glue 作业与 Teradata 环境进行通信。我们不建议通过公共互联网访问 Teradata 环境。

  在 Amazon VPC 中，确定或创建将在执行 AWS Glue 作业时使用的 **VPC**、**子网**和**安全组**。此外，您的 Amazon VPC 配置需要允许您的 Teradata 实例与该位置之间的网络流量。您的作业需要与您的 Teradata 客户端端口建立 TCP 连接。有关 Teradata 端口的更多信息，请参阅 [Teradata 文档](https://docs.teradata.com/r/Teradata-VantageTM-on-AWS-DIY-Installation-and-Administration-Guide/April-2020/Before-Deploying-Vantage-on-AWS-DIY/Security-Groups-and-Ports)。

  根据您的网络布局，可能需要更改 Amazon VPC 和其他联网服务以建立安全的 VPC 连接。有关 AWS 连接的更多信息，请参阅 Teradata 文档中的 [AWS Connectivity Options](https://docs.teradata.com/r/Teradata-VantageCloud-Enterprise/Get-Started/Connecting-Your-Environment/AWS-Connectivity-Options)。

**配置 AWS Glue Teradata 连接：**

1. 在您的 Teradata 配置中，确定或创建 AWS Glue 将用于连接的用户 *teradataUser* 和密码 *teradataPassword*。有关更多信息，请参阅 Teradata 文档中的 [Vantage Security Overview](https://docs.teradata.com/r/Configuring-Teradata-VantageTM-After-Installation/January-2021/Security-Overview/Vantage-Security-Overview)。

1. 在 AWS Secrets Manager 中，使用您的 Teradata 凭证创建一个密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `user` 和值 *teradataUsername* 创建一个键值对。
   + 在选择**键/值对**时，请使用键 `password` 和值 *teradataPassword* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名称 *connectionName*，以供下一步使用。
   + 选择**连接类型**时，请选择 Teradata。
   + 在提供 **JDBC URL** 时，请提供您的实例的 URL。您还可以在 JDBC URL 中将某些连接参数进行硬编码，并以逗号分隔。该 URL 必须符合以下格式：`jdbc:teradata://teradataHostname/ParameterName=ParameterValue,ParameterName=ParameterValue`

     支持的 URL 参数包括：
     + `DATABASE` – 主机上默认要访问的数据库的名称。
     + `DBS_PORT` – 在非标准端口上运行时要使用的数据库端口。
   + 选择**凭证类型**时，请选择 **AWS Secrets Manager**，然后将 **AWS 密钥**设置为 *secretName*。

1. 对于下列情况，您可能需要添加额外的配置：
   + 

     对于通过 Amazon VPC 在 AWS 云端托管的 Teradata 实例
     + 您需要向 AWS Glue 连接提供用于定义 Teradata 安全凭证的 Amazon VPC 连接信息。创建或更新连接时，请在**网络选项**中设置 **VPC**、**子网**和**安全组**。

创建 AWS Glue Teradata 连接后，您需要执行以下操作，然后才能调用您的连接方法：
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 从 Teradata 读取
<a name="aws-glue-programming-etl-connect-teradata-read"></a>

**先决条件**
+ 您要读取的 Teradata 表。您需要表名 *tableName*。
+ 为了提供身份验证信息而配置的 AWS Glue Teradata 连接。完成“*配置 Teradata 连接*”部分的步骤以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

例如：

```
teradata_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type="teradata",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName"
    }
)
```

您还可以提供 SELECT SQL 查询来筛选返回到 DynamicFrame 的结果。您将需要配置 `query`。

例如：

```
teradata_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="teradata",
    connection_options={
        "connectionName": "connectionName",
        "query": "query"
    }
)
```

## 写入 Teradata 表
<a name="aws-glue-programming-etl-connect-teradata-write"></a>

**先决条件：**您要写入的 Teradata 表 *tableName*。**必须首先创建表，然后才能调用连接方法。**

例如：

```
teradata_write = glueContext.write_dynamic_frame.from_options(
    connection_type="teradata",
    connection_options={
        "connectionName": "connectionName", 
        "dbtable": "tableName"
    }
)
```

## Teradata 连接选项参考
<a name="aws-glue-programming-etl-connect-teradata-reference"></a>
+ `connectionName` – 必需。用于读/写。为了向您的连接方法提供身份验证和网络信息而配置的 AWS Glue Teradata 连接的名称。
+ `dbtable` – 对于写入为必填项，对于读取也为必填项，但提供了 `query` 时除外。用于读/写。您的连接方法将与之交互的表的名称。
+ `query` – 用于读取。用来定义从 Teradata 读取数据时要检索的内容的 SQL SELECT 查询。

# Teradata Vantage NOS 连接
<a name="connecting-to-data-teradata-nos"></a>

 Teradata NOS（原生对象存储）连接是 Teradata Vantage 的新连接，其利用 Teradata WRITE\$1NOS 查询从现有表中读取，利用 READ\$1NOS 查询写入表。这些查询使用 Amazon S3 作为暂存目录，因此 Teradata NOS 连接器比现有的 Teradata 连接器（基于 JDBC）更快，尤其在处理大量数据方面。

 在 AWS Glue 5.0 及更高版本中，您可以使用 AWS Glue for Spark 中的 Teradata NOS 连接来读取和写入 Teradata Vantage 中的现有表。您可以使用 SQL 查询来定义要从 Teradata 中读取的信息。您可以通过 AWS Glue 连接使用存储在 AWS Secrets Manager 中的用户名和密码凭证，连接到 Teradata。

 有关 Teradata 的更多信息，请参阅 [Teradata 文档](https://docs.teradata.com/)。

**Topics**
+ [

## 创建 Teradata NOS 连接
](#creating-teradata-nos-connection)
+ [

## 从 Teradata 表读取
](#reading-from-teradata-nos-tables)
+ [

## 写入 Teradata 表
](#writing-to-teradata-nos-tables)
+ [

## Teradata 连接选项参考
](#teradata-nos-connection-option-reference)
+ [

## 在 AWS Glue Visual ETL UI 中提供选项
](#teradata-nos-connection-option-visual-etl-ui)

## 创建 Teradata NOS 连接
<a name="creating-teradata-nos-connection"></a>

要从 AWS Glue 连接到 Teradata NOS，您需要创建 Teradata 凭证并将其存储在某个 AWS Secrets Manager 密钥中，然后将该密钥与 AWS Glue Teradata NOS 连接关联。如果您的 Teradata 实例位于 Amazon VPC 中，则还需要提供 AWS Glue Teradata NOS 连接的联网选项。

 **先决条件：**
+  如果您通过 Amazon VPC 访问您的 Teradata 环境，您的 Amazon VPC 配置应允许您的 AWS Glue 作业与 Teradata 环境进行通信。我们不建议通过公共互联网访问 Teradata 环境。
+  在 Amazon VPC 中，确定或创建 AWS Glue 将在执行作业时使用的 VPC、子网和安全组。此外，您的 Amazon VPC 配置需要允许您的 Teradata 实例与该位置之间的网络流量。您的作业需要与您的 Teradata 客户端端口建立 TCP 连接。有关 Teradata 端口的更多信息，请参阅 [Teradata Vantage 的安全组](https://docs.teradata.com/r/Teradata-VantageTM-on-AWS-DIY-Installation-and-Administration-Guide/April-2020/Before-Deploying-Vantage-on-AWS-DIY/Security-Groups-and-Ports)。
+  根据您的网络布局，可能需要更改 Amazon VPC 和其他联网服务以建立安全的 VPC 连接。有关 AWS 连接的更多信息，请参阅 Teradata 文档中的 [AWS 连接选项](https://docs.teradata.com/r/Teradata-VantageCloud-Enterprise/Get-Started/Connecting-Your-Environment/AWS-Connectivity-Options)。

### 配置 AWS Glue Teradata NOS 连接：
<a name="creating-teradata-nos-connection-procedure"></a>

1.  在您的 Teradata 配置中，确定或创建 AWS Glue 将用于连接的 *teradataUsername* 和 *teradataPassword*。有关更多信息，请参阅 Teradata 文档中的 [Vantage 安全概述](https://docs.teradata.com/r/Configuring-Teradata-VantageTM-After-Installation/January-2021/Security-Overview/Vantage-Security-Overview)。

1.  在 AWS Secrets Manager 中，使用您的 Teradata 凭证创建一个密钥。要在 AWS Secrets Manager 中创建密钥，请按照[在 AWS Secrets Manager 中创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)文档中的可用教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   +  在选择键/值对时，使用值 *teradataUsername* 创建一个键 USERNAME 对。
   +  在选择键/值对时，使用值 *teradataPassword* 创建一个键 PASSWORD 对。

1.  在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](https://docs.aws.amazon.com/glue/latest/dg/console-connections.html)中的步骤创建一个连接。创建连接后，保留连接名称 *connectionName*，以供下一步使用。
   +  选择**连接类型**时，请选择 Teradata Vantage NOS。
   +  在提供 JDBC URL 时，请提供您的实例的 URL。您还可以在 JDBC URL 中将某些连接参数进行硬编码，并以逗号分隔。该 URL 必须符合以下格式：` jdbc:teradata://teradataHostname/ParameterName=ParameterValue,ParameterName=ParameterValue `。
   +  支持的 URL 参数包括：
     +  `DATABASE` – 主机上默认要访问的数据库的名称。
     +  `DBS_PORT` – 在非标准端口上运行时要使用的数据库端口。
   +  选择**凭证类型**时，请选择 AWS Secrets Manager，然后将 **AWS 密钥**设置为 *secretName*。

1.  对于下列情况，您可能需要添加额外的配置：
   +  对于 Amazon VPC 中 AWS 上托管的 Teradata 实例，您需要向 AWS Glue 连接提供用于定义 Teradata 安全凭证的 Amazon VPC 连接信息。创建或更新连接时，在**网络选项**中设置 **VPC**、**子网**和**安全组**。

 创建 AWS Glue Teradata Vantage NOS 连接后，您需要执行以下操作，然后才能调用您的连接方法。

1.  向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。

1.  在 AWS Glue 作业配置中，提供 *connectionName* 作为**连接**下的**附加网络连接**。

## 从 Teradata 表读取
<a name="reading-from-teradata-nos-tables"></a>

### 先决条件：
<a name="w2aac67c11c24b8c41c17b3"></a>
+  您要读取的 Teradata 表。您需要表名 *tableName*。
+  Teradata 环境拥有对 `staging_fs_url` 选项 *stagingFsUrl* 指定的 Amazon S3 路径的写入访问权限。
+  与 AWS Glue 作业关联的 IAM 角色拥有对 `staging_fs_url` 选项指定的 Amazon S3 位置的写入访问权限。
+  为了提供身份验证信息而配置的 AWS Glue Teradata NOS 连接。完成[配置 AWS Glue Teradata NOS 连接：](#creating-teradata-nos-connection-procedure)步骤，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

 示例：

```
teradata_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type= "teradatanos",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName",
        "staging_fs_url": "stagingFsUrl"
    }
)
```

 您还可以提供 SELECT SQL 查询来筛选返回到 DynamicFrame 的结果。您将需要配置查询。如果同时配置 dbTable 和查询，则连接器无法读取数据。例如：

```
teradata_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="teradatanos",
    connection_options={
        "connectionName": "connectionName",
        "query": "query",
        "staging_fs_url": "stagingFsUrl"
    }
)
```

 此外，您可以使用 Spark DataFrame API 从 Teradata 表读取。例如：

```
options = {
    "url": "JDBC_URL",
    "dbtable": "tableName",
    "user": "teradataUsername", # or use "username" as key here
    "password": "teradataPassword",
    "staging_fs_url": "stagingFsUrl"
}
teradata_read_table = spark.read.format("teradatanos").option(**options).load()
```

## 写入 Teradata 表
<a name="writing-to-teradata-nos-tables"></a>

### 先决条件
<a name="writing-to-teradata-nos-tables-prerequisites"></a>
+  您要写入的 Teradata 表：*tableName*。
+  Teradata 环境拥有对 `staging_fs_url` 选项 *stagingFsUrl* 指定的 Amazon S3 位置的读取访问权限。
+  与 AWS Glue 作业关联的 IAM 角色拥有对 `staging_fs_url` 选项指定的 Amazon S3 位置的写入访问权限。
+  为了提供身份验证信息而配置的 AWS Glue Teradata 连接。完成[配置 AWS Glue Teradata NOS 连接：](#creating-teradata-nos-connection-procedure)中的步骤，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。

   例如：

  ```
  teradata_write = glueContext.write_dynamic_frame.from_options(
      frame=dynamicFrame,
      connection_type= "teradatanos",
      connection_options={
          "connectionName": "connectionName", 
          "dbtable": "tableName",
          "staging_fs_url": "stagingFsUrl"
      }
  )
  ```

## Teradata 连接选项参考
<a name="teradata-nos-connection-option-reference"></a>

 **连接和操作选项：**
+  `connectionName`：必需。用于读/写。为了向您的连接方法提供身份验证和网络信息而配置的 AWS Glue Teradata 连接的名称。
+  `staging_fs_url`：必需。用于读/写。Amazon S3 中的一个可写入位置，用于从 Teradata 读取时卸载的数据，及用于在写入 Teradata 时加载到 Redshift 的 Parquet 数据。S3 存储桶与您的 AWS Glue 作业必须位于同一区域。
+  `dbtable` – 对于写入为必填项，对于读取也为必填项，但提供了 `query` 时除外。用于读/写。您的连接方法将与之交互的表的名称。
+  `query` – 用于读取。用来定义从 Teradata 读取数据时要检索的内容的 SQL SELECT 查询。如果提供了 `dbtable` 选项，则您无法通过。
+  `clean_staging_s3_dir`：可选。用于读/写。如果为 true，请在读取或写入之后清理暂存 Amazon S3 对象。默认值为 true。
+  `pre_actions`：可选。用于写入。以分号分隔的 SQL 命令列表，这些命令在 Spark 与 Teradata Vantage 之间传输数据之前执行。
+  `post_actions`：可选。用于写入。以分号分隔的 SQL 命令列表，这些命令在 Spark 与 Teradata Vantage 之间传输数据之后执行。
+  `truncate`：可选。用于写入。如果为 true，则在覆盖模式下写入时，连接器会截断表。如果为 false，则在覆盖模式下写入时，连接器会删除表。默认值为 False。
+  `create_table_script`：可选。用于写入。写入 Teradata Vantage 时用于创建表的 SQL 语句。当您想使用自定义元数据创建表（例如，CREATE MULTISET 或 SET 表或更改主索引）时非常有用。请注意，创建表脚本中使用的表名称应与 `dbtable` 选项中指定的表名称匹配。
+  `partition_size_in_mb`：可选。用于读取。读取暂存 Amazon S3 对象时 Spark 分区的最大大小（以 MB 为单位）。原定设置值为 128。

 您可以在创建 Teradata 节点时提供高级选项。这些选项与编程 Spark 脚本的 AWS Glue 时可用的选项相同。

 请参阅[Teradata Vantage 连接](aws-glue-programming-etl-connect-teradata-home.md)。

 **授权选项：**

 以下是用于提供 AWS 账户凭证的选项，连接器使用这些凭证访问暂存 Amazon S3 存储桶。您可以选择 (1) 根本不提供任何授权选项，并使用从您的 AWS Glue 执行角色生成的临时凭证；或 (2) 提供您创建的授权对象 `auth_object`；或 (3) 如果使用长期凭证，则提供 `aws_access_key_id and aws_secret_access_key`；如果使用临时凭证，则提供 `aws_access_key`、`aws_secret_access_key` 和 `aws_session_token`。
+  `auth_object`：可选。用于访问暂存 Amazon S3 存储桶。在 Teradata 实例中创建的授权对象字符串。如果提供，则连接器将使用此授权对象访问暂存 Amazon S3 存储桶。如果未提供，并且`aws_access_key_id` 和 `aws_secret_access_key` 也未提供，则将从 AWS Glue 执行角色检索临时凭证并供连接器使用。与此授权对象关联的 AWS 账户必须与您的 AWS Glue 作业和暂存 Amazon S3 存储桶位于同一区域，或者已配置跨账户信任。
+  `aws_access_key_id`：可选。用于访问暂存 Amazon S3 存储桶。AWS 账户安全凭证的一部分。如果未提供 `auth_object`，并且 `aws_access_key_id` 与 `aws_secret_access_key` 一起提供，则连接器将使用它们来访问暂存 Amazon S3 存储桶。与此访问密钥关联的 AWS 账户必须与您的 AWS Glue 作业和暂存 Amazon S3 存储桶位于同一区域，或者已配置跨账户信任。
+  `aws_secret_access_key`：可选。用于访问暂存 Amazon S3 存储桶。AWS 账户安全凭证的一部分。如果未提供 `auth_object`，并且 `aws_secret_access_key` 与 `aws_access_key_id` 一起提供，则连接器将使用它们来访问暂存 Amazon S3 存储桶。与此私密密钥关联的 AWS 账户必须与您的 AWS Glue 作业和暂存 Amazon S3 存储桶位于同一区域，或者已配置跨账户信任。
+  `aws_session_token`：可选。用于访问暂存 Amazon S3 存储桶。临时 AWS 账户安全凭证的一部分。应提供 `aws_access_key_id` 和 `aws_secret_access_key`。

## 在 AWS Glue Visual ETL UI 中提供选项
<a name="teradata-nos-connection-option-visual-etl-ui"></a>

 您可以在可视化 ETL 作业 UI 中提供上述所有选项。对于 connectionName 选项，应从 Teradata Vantage NOS 连接下拉列表中进行选择。对于所有其他选项，应通过自定义 Teradata Vantage NOS 属性以键值对的形式提供。

![\[窗口窗格显示已选中 Teradata NOS Vantage 连接。\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/teradata-nos-vantage-connection-options.png)


# Vertica 连接
<a name="aws-glue-programming-etl-connect-vertica-home"></a>

在 AWS Glue 4.0 及更高版本中，您可以使用 AWS Glue for Spark 来读取和写入 Vertica 中的表。您可以使用 SQL 查询来定义要从 Vertica 中读取的信息。您可以通过 AWS Glue 连接并使用存储在 AWS Secrets Manager 中的用户名和密码凭证连接到 Vertica。

有关 Vertica 的更多信息，请参阅 [Vertica 文档](https://www.vertica.com/docs/9.3.x/HTML/Content/Authoring/UsingVerticaOnAWS/UsingVerticaOnAWS.htm)。

## 配置 Vertica 连接
<a name="aws-glue-programming-etl-connect-vertica-configure"></a>

要从 AWS Glue 连接到 Vertica，您需要创建 Vertica 凭证并将其存储在某个 AWS Secrets Manager 密钥中，然后将该密钥关联到某个 Vertica AWS Glue 连接。如果您的 Vertica 实例位于某个 Amazon VPC 中，则还需要提供 AWS Glue Vertica 连接的联网选项。您需要提供读取和写入数据库时用于临时存储的 Amazon S3 存储桶或文件夹。

要从 AWS Glue 连接到 Vertica，您将需要满足一些先决条件：
+ 读取和写入数据库时用于临时存储的 Amazon S3 存储桶或文件夹，也称为 *tempS3Path*。
**注意**  
在 AWS Glue 任务数据预览中使用 Vertica 时，临时文件可能不会自动从 *tempS3Path* 中删除。为确保删除临时文件，请在**数据预览**窗格中选择**结束会话**，以直接结束数据预览会话。  
如果无法保证数据预览会话直接结束，请考虑将 Amazon S3 生命周期配置设置为删除旧数据。我们建议根据最大作业运行时间加一定的裕度移除已存在超过 49 小时的数据。有关配置 Amazon S3 生命周期的更多信息，请参阅 Amazon S3 文档中的 [管理存储生命周期](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)。
+ 对您的 Amazon S3 路径具有适当权限，并且您可以将其关联到您的 AWS Glue 作业角色的 IAM policy。
+ 如果您的 Vertica 实例位于某个 Amazon VPC 中，请确保您的 Amazon VPC 配置允许您的 AWS Glue 作业与 Vertica 实例进行通信，并且无需通过公共互联网路由流量。

  在 Amazon VPC 中，确定或创建 AWS Glue 将在执行作业时使用的 **VPC**、**子网**和**安全组**。此外，您的 Amazon VPC 配置需要允许您的 Vertica 实例与该位置之间的网络流量。您的作业需要与您的 Vertica 客户端端口（默认为 5433）建立 TCP 连接。根据您的网络布局，这可能需要更改安全组规则、网络 ACL、NAT 网关和对等连接。

然后您可以继续配置 AWS Glue 以便与 Vertica 配合使用。

**配置 Vertica 连接：**

1. 在 AWS Secrets Manager 中，使用您的 Vertica 凭证 *verticaUsername* 和 *verticaPassword* 创建一个密钥。要在 Secrets Manager 中创建密钥，请按照 AWS Secrets Manager 文档中[创建 AWS Secrets Manager 密钥](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)中的教程进行操作。创建密钥后，保留密钥名称 *secretName*，以供下一步使用。
   + 在选择**键/值对**时，请使用键 `user` 和值 *verticaUsername* 创建一个键值对。
   + 在选择**键/值对**时，请使用键 `password` 和值 *verticaPassword* 创建一个键值对。

1. 在 AWS Glue 控制台中，按照 [添加 AWS Glue 连接](console-connections.md) 中的步骤创建一个连接。创建连接后，保留连接名称 *connectionName*，以供下一步使用。
   + 选择**连接类型**时，请选择 Vertica。
   + 选择 **Vertica 主机**时，请提供您安装了 Vertica 的主机名。
   + 选择 **Vertica 端口**时，请提供可用于访问 Vertica 安装的端口。
   + 选择 **AWS 密钥**时，请提供 *secretName*。

1. 对于下列情况，您可能需要添加额外的配置：
   + 

     对于通过 Amazon VPC 在 AWS 云端托管的 Vertica 实例
     + 向 AWS Glue 连接提供用于定义 Vertica 安全凭证的 Amazon VPC 连接信息。创建或更新连接时，请在**网络选项**中设置 **VPC**、**子网**和**安全组**。

创建 AWS Glue Vertica 连接后，您需要执行以下操作，然后才能调用您的连接方法：
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予对 *tempS3Path* 的权限。
+ 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 *secretName* 的权限。
+ 在 AWS Glue 作业配置中，提供 *connectionName* 作为**附加网络连接**。

## 从 Vertica 读取
<a name="aws-glue-programming-etl-connect-vertica-read"></a>

**先决条件** 
+ 您要读取的 Vertica 表。您需要 Vertica 数据库名 *dbName* 和表名 *tableName*。
+ 为了提供身份验证信息而配置的 AWS Glue Vertica 连接。完成上一节“配置 Vertica 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。
+ 前面提到的用作临时存储的 Amazon S3 存储桶或文件夹。您将需要名称 *tempS3Path*。您将需要使用 `s3a` 协议连接到此位置。

例如：

```
dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="vertica",
    connection_options={
        "connectionName": "connectionName",
        "staging_fs_url": "s3a://tempS3Path",
        "db": "dbName",
        "table": "tableName",
    }
)
```

您还可以提供 SELECT SQL 查询来筛选返回到 DynamicFrame 的结果，或者访问来自多个表的数据集。

例如：

```
dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="vertica",
    connection_options={
        "connectionName": "connectionName",
        "staging_fs_url": "s3a://tempS3Path",
        "db": "dbName",
        "query": "select * FROM tableName",
    },
)
```

## 写入 Vertica 表
<a name="aws-glue-programming-etl-connect-vertica-write"></a>

此示例会将来自现有 DynamicFrame *dynamicFrame* 的信息写入 Vertica。如果表中已经含有信息，AWS Glue 会将来自 DynamicFrame 的数据附加到现有信息之后。

**先决条件** 
+ 您要写入的当前已有或需要的表名 *tableName*。您还需要相应的 Vertica 数据库名 *dbName*。
+ 为了提供身份验证信息而配置的 AWS Glue Vertica 连接。完成上一节“配置 Vertica 连接”中的步骤**，以配置您的身份验证信息。您需要 AWS Glue 连接的名称 *connectionName*。
+ 前面提到的用作临时存储的 Amazon S3 存储桶或文件夹。您将需要名称 *tempS3Path*。您将需要使用 `s3a` 协议连接到此位置。

例如：

```
glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="vertica",
    connection_options={
        "connectionName": "connectionName",
        "staging_fs_url": "s3a://tempS3Path",
        "db": "dbName",
        "table": "tableName",
    }
)
```

## Vertica 连接选项参考
<a name="aws-glue-programming-etl-connect-vertica-reference"></a>
+ `connectionName` – 必需。用于读/写。为了向您的连接方法提供身份验证和网络信息而配置的 AWS Glue Vertica 连接的名称。
+ `db` – 必需。用于读/写。您的连接方法将与之交互的 Vertica 中数据库的名称。
+ `dbSchema` – 如果需要标识您的表，则为必填项。用于读/写。默认值：`public`。您的连接方法将与之交互的 Schema 的名称。
+ `table` – 对于写入为必填项，对于读取也为必填项，但提供了 `query` 时除外。用于读/写。您的连接方法将与之交互的表的名称。
+ `query` – 用于读取。用来定义从 Teradata 读取数据时要检索的内容的 SQL SELECT 查询。
+ `staging_fs_url` – 必需。用于读/写。有效值：`s3a` URL。用作临时存储的 Amazon S3 存储桶或文件夹的 URL。

## AWS Glue 5.0 for Spark 中 ETL 的 DataFrame 选项
<a name="aws-glue-programming-etl-connect-dataframe"></a>

DataFrame 是一个类似于表的按命名列组织的数据集，并支持函数式（map/reduce/filter/等）操作和 SQL 操作（select、project、aggregate）。

要为 Glue 支持的数据来源创建 DataFrame，需要以下项：
+ 数据来源连接器 `ClassName`
+ 数据来源连接 `Options`

同样，要将 DataFrame 写入 Glue 支持的数据接收器，也需要相同项：
+ 数据接收器连接器 `ClassName`
+ 数据接收器连接 `Options`

请注意，DataFrame 不支持 AWS Glue 功能（例如作业书签）和 DynamicFrame 选项（例如 `connectionName`）。有关 DataFrame 及其支持的操作的更多详细信息，请参阅 [DataFrame](https://spark.apache.org/docs/3.5.2/api/python/reference/pyspark.sql/dataframe.html) 的 Spark 文档。

### 指定连接器类名
<a name="aws-glue-programming-etl-connect-dataframe-classname"></a>

要指定数据来源/接收器的 `ClassName`，请使用 `.format` 选项提供定义数据来源/接收器的相应连接器 `ClassName`。

**JDBC 连接器**  
对于 JDBC 连接器，请指定 `jdbc` 作为 `.format` 选项的值，并在 `driver` 选项中提供 JDBC 驱动程序 `ClassName`。

```
df = spark.read.format("jdbc").option("driver", "<DATA SOURCE JDBC DRIVER CLASSNAME>")...

df.write.format("jdbc").option("driver", "<DATA SINK JDBC DRIVER CLASSNAME>")...
```

下表列出了 AWS Glue for DataFrames 支持的数据来源的 JDBC 驱动程序 `ClassName`。

| 数据来源 | 驱动程序类名 | 
| --- |--- |
| PostgreSQL | org.postgresql.Driver | 
| Oracle | oracle.jdbc.driver.OracleDriver | 
| SQLServer | com.microsoft.sqlserver.jdbc.SQLServerDriver | 
| MySQL | com.mysql.jdbc.Driver | 
| SAPHana | com.sap.db.jdbc.Driver | 
| Teradata | com.teradata.jdbc.TeraDriver | 

**Spark 连接器**  
对于 Spark 连接器，请将连接器的 `ClassName` 指定为 `.format` 选项的值。

```
df = spark.read.format("<DATA SOURCE CONNECTOR CLASSNAME>")...

df.write.format("<DATA SINK CONNECTOR CLASSNAME>")...
```

下表列出了 AWS Glue for DataFrames 中支持的数据来源的 Spark 连接器 `ClassName`。

| 数据来源 | 类名 | 
| --- |--- |
| MongoDB/DocumentDB | glue.spark.mongodb | 
| Redshift | io.github.spark\$1redshift\$1community.spark.redshift | 
| AzureCosmos | cosmos.oltp | 
| AzureSQL | com.microsoft.sqlserver.jdbc.spark | 
| BigQuery | com.google.cloud.spark.bigquery | 
| OpenSearch | org.opensearch.spark.sql | 
| Snowflake | net.snowflake.spark.snowflake | 
| Vertica | com.vertica.spark.datasource.VerticaSource | 

### 指定连接选项
<a name="aws-glue-programming-etl-connect-dataframe-connection-options"></a>

要指定与数据来源/接收器的连接的 `Options`，请使用 `.option(<KEY>, <VALUE>)` 提供单个选项或使用 `.options(<MAP>)` 提供多个选项作为键值映射。

每个数据来源/接收器都支持自己的一组连接 `Options`。有关可用 `Options` 的详细信息，请参阅下表中列出的特定数据来源/接收器 Spark 连接器的公共文档。
+ [JDBC](https://spark.apache.org/docs/3.5.2/sql-data-sources-jdbc.html)
+ [MongoDB/DocumentDB](https://www.mongodb.com/docs/spark-connector/v10.4/)
+ [Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)
+ [AzureCosmos](https://github.com/Azure/azure-cosmosdb-spark)
+ [AzureSQL](https://learn.microsoft.com/en-us/sql/connect/spark/connector?view=sql-server-ver16)
+ [BigQuery](https://cloud.google.com/dataproc/docs/tutorials/bigquery-connector-spark-example)
+ [OpenSearch](https://github.com/opensearch-project/opensearch-hadoop/blob/main/USER_GUIDE.md#apache-spark)
+ [Snowflake](https://docs.snowflake.com/en/user-guide/spark-connector-use#setting-configuration-options-for-the-connector)
+ [Vertica](https://github.com/vertica/spark-connector)

### 示例
<a name="aws-glue-programming-etl-connect-dataframe-examples"></a>

以下示例从 PostgreSQL 读取并写入 SnowFlake：

**Python**  
示例：

```
from awsglue.context import GlueContext
from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()

dataSourceClassName = "jdbc"
dataSourceOptions = {
  "driver": "org.postgresql.Driver",
  "url": "<url>",
  "user": "<user>",
  "password": "<password>",
  "dbtable": "<dbtable>",
}

dataframe = spark.read.format(className).options(**options).load()

dataSinkClassName = "net.snowflake.spark.snowflake"
dataSinkOptions = {
  "sfUrl": "<url>",
  "sfUsername": "<username>",
  "sfPassword": "<password>",
  "sfDatabase" -> "<database>",                              
  "sfSchema" -> "<schema>",                       
  "sfWarehouse" -> "<warehouse>"  
}

dataframe.write.format(dataSinkClassName).options(**dataSinkOptions).save()
```

**Scala**  
示例：

```
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder().getOrCreate()

val dataSourceClassName = "jdbc"
val dataSourceOptions = Map(
  "driver" -> "org.postgresql.Driver",
  "url" -> "<url>",
  "user" -> "<user>",
  "password" -> "<password>",
  "dbtable" -> "<dbtable>"
)

val dataframe = spark.read.format(dataSourceClassName).options(dataSourceOptions).load()

val dataSinkClassName = "net.snowflake.spark.snowflake"
val dataSinkOptions = Map(
  "sfUrl" -> "<url>",
  "sfUsername" -> "<username>",
  "sfPassword" -> "<password>",
  "sfDatabase" -> "<database>",
  "sfSchema" -> "<schema>",
  "sfWarehouse" -> "<warehouse>"
)

dataframe.write.format(dataSinkClassName).options(dataSinkOptions).save()
```

## 自定义和 AWS Marketplace connectionType 值
<a name="aws-glue-programming-etl-connect-market"></a>

这些功能包括：
+ `"connectionType": "marketplace.athena"`：指定与 Amazon Athena 数据存储的连接。连接使用来自 AWS Marketplace 的连接器。
+ `"connectionType": "marketplace.spark"`：指定与 Apache Spark 数据存储的连接。连接使用来自 AWS Marketplace 的连接器。
+ `"connectionType": "marketplace.jdbc"`：指定与 JDBC 数据存储的连接。连接使用来自 AWS Marketplace 的连接器。
+ `"connectionType": "custom.athena"`：指定与 Amazon Athena 数据存储的连接。连接使用您上传到 AWS Glue Studio 的自定义连接器。
+ `"connectionType": "custom.spark"`：指定与 Apache Spark 数据存储的连接。连接使用您上传到 AWS Glue Studio 的自定义连接器。
+ `"connectionType": "custom.jdbc"`：指定与 JDBC 数据存储的连接。连接使用您上传到 AWS Glue Studio 的自定义连接器。

### 适用于类型 custom.jdbc 或 marketplace.jdbc 的连接选项
<a name="marketplace-jdbc-connect-options"></a>
+ `className` – 字符串，必需，驱动程序类名称。
+ `connectionName` – 字符串，必需，与连接器关联的连接的名称。
+ `url` – 字符串，必需，用于建立与数据源的连接且带占位符（`${}`）的 JDBC URL。占位符 `${secretKey}` 替换为 AWS Secrets Manager 中同名的密钥。有关构建 URL 的详细信息，请参阅数据存储文档。
+ `secretId` 或 `user/password` – 字符串，必需，用于检索 URL 的凭证。
+ `dbTable` 或 `query` – 字符串，必需，从中获取数据的表或 SQL 查询。您可以指定 `dbTable` 或 `query`，但不能同时指定两者。
+ `partitionColumn` – 字符串，可选，用于分区的整数列的名称。此选项仅在包含 `lowerBound`、`upperBound` 和 `numPartitions` 时有效。此选项的工作方式与 Spark SQL JDBC 阅读器中的工作方式相同。有关更多信息，请参阅《Apache Spark SQL、DataFrame 和 Dataset 指南》中的 [JDBC 转换到其他数据库](https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html)**。

  `lowerBound` 和 `upperBound` 值用于确定分区步长，而不是用于筛选表中的行。对表中的所有行进行分区并返回。
**注意**  
使用查询（而不是表名称）时，您应验证查询是否适用于指定的分区条件。例如：  
如果您的查询格式为 `"SELECT col1 FROM table1"`，则在使用分区列的查询结尾附加 `WHERE` 子句，以测试查询。
如果您的查询格式为 `SELECT col1 FROM table1 WHERE col2=val"`，则通过 `AND` 和使用分区列的表达式扩展 `WHERE` 子句，以测试查询。
+ `lowerBound` – 整数，可选，用于确定分区步长的最小 `partitionColumn` 值。
+ `upperBound` – 整数，可选，用于确定分区步长的最大 `partitionColumn` 值。
+ `numPartitions` – 整数，可选，分区数。此值以及 `lowerBound`（包含）和 `upperBound`（排除）为用于拆分 `partitionColumn` 而生成的 `WHERE` 子句表达式构成分区步长。
**重要**  
请注意分区的数量，因为分区过多可能会导致外部数据库系统出现问题。
+ `filterPredicate` – 字符串，可选，用于筛选源数据的额外条件子句。例如：

  ```
  BillingCity='Mountain View'
  ```

  使用*查询*（而不是*表*名称）时，您应验证查询是否适用于指定的 `filterPredicate`。例如：
  + 如果您的查询格式为 `"SELECT col1 FROM table1"`，则在使用筛选条件谓词的查询结尾附加 `WHERE` 子句，以测试查询。
  + 如果您的查询格式为 `"SELECT col1 FROM table1 WHERE col2=val"`，则通过 `AND` 和使用筛选条件谓词的表达式扩展 `WHERE` 子句，以测试查询。
+ `dataTypeMapping` – 目录，可选，用于构建从 **JDBC** 数据类型到 **Glue** 数据类型的映射的自定义数据类型映射。例如，选项 `"dataTypeMapping":{"FLOAT":"STRING"}` 会通过调用驱动程序的 `ResultSet.getString()` 方法，将 JDBC 类型 `FLOAT` 的数据字段映射到 Java `String` 类型，并将其用于构建 AWS Glue 记录。`ResultSet` 对象由每个驱动程序实现，因此行为特定于您使用的驱动程序。请参阅 JDBC 驱动程序的文档，了解驱动程序执行转换的方式。
+ 目前受支持的 AWS Glue 数据类型包括：
  + DATE
  + string
  + TIMESTAMP
  + INT
  + FLOAT
  + LONG
  + BIGDECIMAL
  + BYTE
  + SHORT
  + DOUBLE

   支持的 JDBC 数据类型为 [Java8 java.sql.types](https://docs.oracle.com/javase/8/docs/api/java/sql/Types.html)。

  默认数据类型映射（从 JDBC 到 AWS Glue）如下：
  +  DATE -> DATE
  +  VARCHAR -> STRING
  +  CHAR -> STRING
  +  LONGNVARCHAR -> STRING
  +  TIMESTAMP -> TIMESTAMP
  +  INTEGER -> INT
  +  FLOAT -> FLOAT
  +  REAL -> FLOAT
  +  BIT -> BOOLEAN
  +  BOOLEAN -> BOOLEAN
  +  BIGINT -> LONG
  +  DECIMAL -> BIGDECIMAL
  +  NUMERIC -> BIGDECIMAL
  +  TINYINT -> SHORT
  +  SMALLINT -> SHORT
  +  DOUBLE -> DOUBLE

  如果将自定义数据类型映射与选项 `dataTypeMapping` 结合使用，则可以覆盖默认数据类型映射。只有 `dataTypeMapping` 选项中列出的 JDBC 数据类型会受到影响；默认映射适用于所有其他 JDBC 数据类型。如果需要，您可以为其他 JDBC 数据类型添加映射。如果默认映射或自定义映射中均未包含 JDBC 数据类型，则数据类型默认转换为 AWS Glue `STRING` 数据类型。

以下 Python 代码示例演示了如何使用 AWS Marketplace JDBC 驱动程序从 JDBC 数据库读取数据。它演示了如何从数据库读取数据并将数据写入 S3 位置。

```
    import sys
    from awsglue.transforms import *
    from awsglue.utils import getResolvedOptions
    from pyspark.context import SparkContext
    from awsglue.context import GlueContext
    from awsglue.job import Job
     
    ## @params: [JOB_NAME]
    args = getResolvedOptions(sys.argv, ['JOB_NAME'])
     
    sc = SparkContext()
    glueContext = GlueContext(sc)
    spark = glueContext.spark_session
    job = Job(glueContext)
    job.init(args['JOB_NAME'], args)
    ## @type: DataSource
    ## @args: [connection_type = "marketplace.jdbc", connection_options = 
     {"dataTypeMapping":{"INTEGER":"STRING"},"upperBound":"200","query":"select id, 
       name, department from department where id < 200","numPartitions":"4",
       "partitionColumn":"id","lowerBound":"0","connectionName":"test-connection-jdbc"},
        transformation_ctx = "DataSource0"]
    ## @return: DataSource0
    ## @inputs: []
    DataSource0 = glueContext.create_dynamic_frame.from_options(connection_type = 
      "marketplace.jdbc", connection_options = {"dataTypeMapping":{"INTEGER":"STRING"},
      "upperBound":"200","query":"select id, name, department from department where 
       id < 200","numPartitions":"4","partitionColumn":"id","lowerBound":"0",
       "connectionName":"test-connection-jdbc"}, transformation_ctx = "DataSource0")
    ## @type: ApplyMapping
    ## @args: [mappings = [("department", "string", "department", "string"), ("name", "string",
      "name", "string"), ("id", "int", "id", "int")], transformation_ctx = "Transform0"]
    ## @return: Transform0
    ## @inputs: [frame = DataSource0]
    Transform0 = ApplyMapping.apply(frame = DataSource0, mappings = [("department", "string",
      "department", "string"), ("name", "string", "name", "string"), ("id", "int", "id", "int")], 
       transformation_ctx = "Transform0")
    ## @type: DataSink
    ## @args: [connection_type = "s3", format = "json", connection_options = {"path": 
     "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
    ## @return: DataSink0
    ## @inputs: [frame = Transform0]
    DataSink0 = glueContext.write_dynamic_frame.from_options(frame = Transform0, 
      connection_type = "s3", format = "json", connection_options = {"path": 
      "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0")
    job.commit()
```

### 适用于类型 custom.athena 或 marketplace.athena 的连接选项
<a name="marketplace-athena-connect-options"></a>
+ `className` – 字符串，必需，驱动程序类名称。当您使用 Athena-CloudWatch 连接器时，此参数值是类名称（例如 `"com.amazonaws.athena.connectors"`）的前缀。Athena-CloudWatch 连接器由两个类组成：元数据处理程序和记录处理程序。如果您在此处提供通用前缀，则 API 会根据该前缀加载正确的类。
+ `tableName` – 字符串，必需，要读取的 CloudWatch 日志流的名称。此代码段使用特别视图名称 `all_log_streams`，这意味着返回的动态数据框将包含日志组中所有日志流的数据。
+ `schemaName` – 字符串，必需，要从中读取数据的 CloudWatch 日志流的名称。例如 `/aws-glue/jobs/output`。
+ `connectionName` – 字符串，必需，与连接器关联的连接的名称。

有关此连接器的其他选项，请参阅 GitHub 上的 [Amazon Athena CloudWatch 连接器自述](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-cloudwatch)文件。

以下 Python 代码示例演示了如何从使用 AWS Marketplace 连接器的 Athena 数据存储读取数据。它演示了如何从 Athena 读取数据并将数据写入 S3 位置。

```
    import sys
    from awsglue.transforms import *
    from awsglue.utils import getResolvedOptions
    from pyspark.context import SparkContext
    from awsglue.context import GlueContext
    from awsglue.job import Job
     
    ## @params: [JOB_NAME]
    args = getResolvedOptions(sys.argv, ['JOB_NAME'])
     
    sc = SparkContext()
    glueContext = GlueContext(sc)
    spark = glueContext.spark_session
    job = Job(glueContext)
    job.init(args['JOB_NAME'], args)
    ## @type: DataSource
    ## @args: [connection_type = "marketplace.athena", connection_options = 
     {"tableName":"all_log_streams","schemaName":"/aws-glue/jobs/output",
      "connectionName":"test-connection-athena"}, transformation_ctx = "DataSource0"]
    ## @return: DataSource0
    ## @inputs: []
    DataSource0 = glueContext.create_dynamic_frame.from_options(connection_type = 
      "marketplace.athena", connection_options = {"tableName":"all_log_streams",,
      "schemaName":"/aws-glue/jobs/output","connectionName":
      "test-connection-athena"}, transformation_ctx = "DataSource0")
    ## @type: ApplyMapping
    ## @args: [mappings = [("department", "string", "department", "string"), ("name", "string",
      "name", "string"), ("id", "int", "id", "int")], transformation_ctx = "Transform0"]
    ## @return: Transform0
    ## @inputs: [frame = DataSource0]
    Transform0 = ApplyMapping.apply(frame = DataSource0, mappings = [("department", "string",
      "department", "string"), ("name", "string", "name", "string"), ("id", "int", "id", "int")], 
       transformation_ctx = "Transform0")
    ## @type: DataSink
    ## @args: [connection_type = "s3", format = "json", connection_options = {"path": 
     "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
    ## @return: DataSink0
    ## @inputs: [frame = Transform0]
    DataSink0 = glueContext.write_dynamic_frame.from_options(frame = Transform0, 
      connection_type = "s3", format = "json", connection_options = {"path": 
      "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0")
    job.commit()
```

### 适用于类型 custom.spark 或 marketplace.spark 的连接选项
<a name="marketplace-spark-connect-options"></a>
+ `className` – 字符串，必需，连接器类名称。
+ `secretId` – 字符串，可选，用于检索连接器连接的凭证。
+ `connectionName` – 字符串，必需，与连接器关联的连接的名称。
+ 其他选项取决于数据存储。例如，OpenSearch 配置选项以前缀 `es` 开头，正如[适用于 Apache Hadoop 的 Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/hadoop/current/configuration.html) 文档中所述。Spark 与 Snowflake 的连接使用 `sfUser` 和 `sfPassword` 等连接，正如《连接 Snowflake》**指南中的[使用 Spark 连接器](https://docs.snowflake.com/en/user-guide/spark-connector-use.html)所述。

以下 Python 代码示例演示了如何从使用 `marketplace.spark` 连接的 OpenSearch 数据存储读取数据。

```
    import sys
    from awsglue.transforms import *
    from awsglue.utils import getResolvedOptions
    from pyspark.context import SparkContext
    from awsglue.context import GlueContext
    from awsglue.job import Job
     
    ## @params: [JOB_NAME]
    args = getResolvedOptions(sys.argv, ['JOB_NAME'])
     
    sc = SparkContext()
    glueContext = GlueContext(sc)
    spark = glueContext.spark_session
    job = Job(glueContext)
    job.init(args['JOB_NAME'], args)
    ## @type: DataSource
    ## @args: [connection_type = "marketplace.spark", connection_options = {"path":"test",
      "es.nodes.wan.only":"true","es.nodes":"https://<AWS endpoint>",
      "connectionName":"test-spark-es","es.port":"443"}, transformation_ctx = "DataSource0"]
    ## @return: DataSource0
    ## @inputs: []
    DataSource0 = glueContext.create_dynamic_frame.from_options(connection_type = 
      "marketplace.spark", connection_options = {"path":"test","es.nodes.wan.only":
      "true","es.nodes":"https://<AWS endpoint>","connectionName":
      "test-spark-es","es.port":"443"}, transformation_ctx = "DataSource0")
    ## @type: DataSink
    ## @args: [connection_type = "s3", format = "json", connection_options = {"path": 
         "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
    ## @return: DataSink0
    ## @inputs: [frame = DataSource0]
    DataSink0 = glueContext.write_dynamic_frame.from_options(frame = DataSource0, 
       connection_type = "s3", format = "json", connection_options = {"path": 
       "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0")
    job.commit()
```

## 常规选项
<a name="aws-glue-programming-etl-connect-general-options"></a>

本节中的选项以 `connection_options` 形式提供，但不是专门适用于一个连接器。

配置书签时通常使用以下参数。它们可能适用于 Amazon S3 或 JDBC 工作流程。有关更多信息，请参阅 [使用作业书签](programming-etl-connect-bookmarks.md)。
+ `jobBookmarkKeys` - 列名称的数组。
+ `jobBookmarkKeysSortOrder` - 定义如何根据排序顺序比较值的字符串。有效值：`"asc"`、`"desc"`。
+ `useS3ListImplementation` - 用于在列出 Amazon S3 存储桶内容时管理内存性能。有关更多信息，请参阅 [Optimize memory management in AWS Glue](https://aws.amazon.com/blogs/big-data/optimize-memory-management-in-aws-glue/)。

# AWS Glue for Spark 中的输入和输出的数据格式选项
<a name="aws-glue-programming-etl-format"></a>

这些页面提供有关 AWS Glue for Spark 支持的数据格式的功能支持和配置参数的信息。有关这些信息用法和适用性的说明，请参阅以下内容。

## AWS Glue 中跨数据格式的支持功能
<a name="aws-glue-programming-etl-format-features"></a>

 每种数据格式可能支持不同的 AWS Glue 功能。您的数据格式是否以下常用功能应视其类型而定。请参阅数据格式的相关文档，了解如何利用我们的功能满足您的需求。


|  |  | 
| --- |--- |
| 读取 | AWS Glue 无需额外资源（例如连接器）即可识别和解释此数据格式。 | 
| 写入 | AWS Glue 可以在没有额外资源的情况下以此格式写入数据。您可以在任务中加入第三方库并使用标准 Apache Spark 函数来写入数据，就像在其他 Spark 环境中一样。有关库的更多信息，请参阅 [将 Python 库与 AWS Glue 结合使用](aws-glue-programming-python-libraries.md)。 | 
| 流式处理读取 | AWS Glue 可以从 Apache Kafka、Amazon Managed Streaming for Apache Kafka 或 Amazon Kinesis 消息流中识别和解释此数据格式。我们期望流以一致的格式呈现数据，因此数据将读入为 DataFrames。 | 
| 对小文件进行分组 | AWS Glue 在执行 AWS Glue 转换时可以将文件合并到发送至每个节点的批处理工作中。这可以显著提高涉及大量小文件的工作负载性能。有关更多信息，请参阅 [以较大的组读取输入文件](grouping-input-files.md)。 | 
| 作业书签 | AWS Glue 可以跟踪转换的进度，在任务运行期间使用任务书签对相同数据集执行相同的工作。这可以提高涉及多个数据集且其中只需要处理上次任务运行之后产生的新数据的工作负载性能。有关更多信息，请参阅 [使用作业书签跟踪已处理的数据](monitor-continuations.md)。 | 

## AWS Glue 中用于与数据格式交互的参数
<a name="aws-glue-programming-etl-format-parameters"></a>

某些 AWS Glue 连接类型支持多种 `format` 类型，这需要您在使用类似 `GlueContext.write_dynamic_frame.from_options` 的方法时，使用 `format_options` 对象指定关于数据格式的信息。
+ `s3` – 有关更多信息，请参阅 AWS Glue 中的 ETL 的连接类型和选项：[S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。您还可以查看关于支持此连接类型的方法的文档：Python 中的 [create\$1dynamic\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 和 [write\$1dynamic\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 以及相应的 Scala 方法 [def getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 和 [def getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat)。

  
+ `kinesis` – 有关更多信息，请参阅 AWS Glue 中的 ETL 的连接类型和选项：[Kinesis 连接参数](aws-glue-programming-etl-connect-kinesis-home.md#aws-glue-programming-etl-connect-kinesis)。您还可以查看关于支持此连接类型的方法的文档：[create\$1data\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create-dataframe-from-options) 以及相应的 Scala 方法 [def createDataFrameFromOptions](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-createDataFrameFromOptions)。
+ `kafka` – 有关更多信息，请参阅 AWS Glue 中的 ETL 的连接类型和选项：[Kafka 连接参数](aws-glue-programming-etl-connect-kafka-home.md#aws-glue-programming-etl-connect-kafka)。您还可以查看关于支持此连接类型的方法的文档：[create\$1data\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create-dataframe-from-options) 以及相应的 Scala 方法 [def createDataFrameFromOptions](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-createDataFrameFromOptions)。

有些连接类型不需要 `format_options`。例如，在正常使用过程中，连接至关系数据库的 JDBC 连接以一致的表格数据格式检索数据。因此，从 JDBC 连接中进行读取不需要 `format_options`。

某些在 Glue 中读取和写入数据的方法不需要 `format_options`。例如，通过 AWS Glue 爬网程序使用 `GlueContext.create_dynamic_frame.from_catalog`。爬网程序决定数据的形状。使用爬网程序时，AWS Glue 分类器将检查数据，以便就如何表示数据格式做出明智决策。然后，它会将数据表示形式存储在 AWS Glue 数据目录中，此数据目录可以在 AWS Glue ETL 脚本中使用，以通过 `GlueContext.create_dynamic_frame.from_catalog` 方法检索数据。爬网程序无需您手动指定有关数据格式的信息。

对于访问 AWS Lake Formation 受管表的任务，AWS Glue 支持读取和写入 Lake Formation 受管表支持的所有格式。有关当前 AWS Lake Formation 受管表支持的格式列表，请参阅 *AWS Lake Formation 开发人员指南*中的[受管表的注释和限制](https://docs.aws.amazon.com/lake-formation/latest/dg/governed-table-restrictions.html)。

**注意**  
对于写入 Apache Parquet，AWS Glue ETL 仅支持为针对动态帧进行优化的自定义 Parquet 编写器类型指定选项来写入受管表。使用 `parquet` 格式写入受管表时，应在表参数中添加值为 `true` 的键 `useGlueParquetWriter`。

**Topics**
+ [

## AWS Glue 中跨数据格式的支持功能
](#aws-glue-programming-etl-format-features)
+ [

## AWS Glue 中用于与数据格式交互的参数
](#aws-glue-programming-etl-format-parameters)
+ [

# 在 AWS Glue 中使用 CSV 格式
](aws-glue-programming-etl-format-csv-home.md)
+ [

# 在 AWS Glue 中使用 Parquet 格式
](aws-glue-programming-etl-format-parquet-home.md)
+ [

# 在 AWS Glue 中使用 XML 格式
](aws-glue-programming-etl-format-xml-home.md)
+ [

# 在 AWS Glue 中使用 Avro 格式
](aws-glue-programming-etl-format-avro-home.md)
+ [

# 在 AWS Glue 中使用 grokLog 格式
](aws-glue-programming-etl-format-grokLog-home.md)
+ [

# 在 AWS Glue 中使用 Ion 格式
](aws-glue-programming-etl-format-ion-home.md)
+ [

# 在 AWS Glue 中使用 JSON 格式
](aws-glue-programming-etl-format-json-home.md)
+ [

# 在 AWS Glue 中使用 ORC 格式
](aws-glue-programming-etl-format-orc-home.md)
+ [

# 在 AWS Glue ETL 任务中使用数据湖框架
](aws-glue-programming-etl-datalake-native-frameworks.md)
+ [

## 共享配置参考
](#aws-glue-programming-etl-format-shared-reference)

# 在 AWS Glue 中使用 CSV 格式
<a name="aws-glue-programming-etl-format-csv-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以 CSV 数据格式存储或传输，本文档将向您介绍供您使用 AWS Glue 中的数据的可用功能。

 AWS Glue 支持逗号分隔值（CSV）格式。此格式是一种基于行的最小数据格式。CSV 通常不严格遵守某一标准，但您可以参考 [RFC 4180](https://tools.ietf.org/html/rfc4180) 和 [RFC 7111](https://tools.ietf.org/html/rfc7111) 了解更多信息。

您可以使用 AWS Glue 从 Amazon S3 和流式传输源读取 CSV，以及将 CSV 写入 Amazon S3。您可以读取并写入包含 S3 中的 CSV 文件的 `bzip` 和 `gzip` 存档。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。

下表显示了哪些常用 AWS Glue 功能支持 CSV 格式选项。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 支持 | 支持 | 支持 | 支持 | 

## 示例：从 S3 读取 CSV 文件或文件夹
<a name="aws-glue-programming-etl-format-csv-read"></a>

 **先决条件：**您将需要至您想要读取的 CSV 文件或文件夹的 S3 路径（`s3path`）。

 **配置：**在函数选项中，请指定 `format="csv"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中配置读取器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。您可以配置读取器如何解释 `format_options` 中的 CSV 文件。有关详细信息，请参阅 [CSV 配置参考](#aws-glue-programming-etl-format-csv-reference)。

以下 AWS Glue ETL 脚本显示了从 S3 读取 CSV 文件或文件夹的过程。

 我们提供自定义的 CSV 读取器，其中包含通过 `optimizePerformance` 配置键针对常见工作流进行的性能优化。要确定此读取器是否适合您的工作负载，请参阅 [使用向量化 SIMD CSV 读取器优化读取性能](#aws-glue-programming-etl-format-simd-csv-reader)。

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
# Example: Read CSV from S3
# For show, we handle a CSV with a header row.  Set the withHeader option.
# Consider whether optimizePerformance is right for your workflow.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="csv",
    format_options={
        "withHeader": True,
        # "optimizePerformance": True,
    },
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
dataFrame = spark.read\
    .format("csv")\
    .option("header", "true")\
    .load("s3://s3path")
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 操作。

```
// Example: Read CSV from S3
// For show, we handle a CSV with a header row.  Set the withHeader option.
// Consider whether optimizePerformance is right for your workflow.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      formatOptions=JsonOptions("""{"withHeader": true}"""),
      connectionType="s3",
      format="csv",
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
  }
}
```

您还可以使用脚本（`org.apache.spark.sql.DataFrame`）中的 DataFrames。

```
val dataFrame = spark.read
  .option("header","true")
  .format("csv")
  .load("s3://s3path“)
```

------

## 示例：将 CSV 文件和文件夹写入 S3
<a name="aws-glue-programming-etl-format-csv-write"></a>

 **先决条件：**您将需要一个初始化的 DataFrame（`dataFrame`）或 DynamicFrame（`dynamicFrame`）。您还需要预期 S3 输出路径 `s3path`。

 **配置：**在函数选项中，请指定 `format="csv"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中配置编写器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。您可以配置自己的操作在 `format_options` 中写入文件的内容的方式。有关详细信息，请参阅 [CSV 配置参考](#aws-glue-programming-etl-format-csv-reference)。以下 AWS Glue ETL 脚本显示了将 CSV 文件和文件夹写入 S3 的过程。

------
#### [ Python ]

在本示例中，使用 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 方法。

```
# Example: Write CSV to S3
# For show, customize how we write string type values.  Set quoteChar to -1 so our values are not quoted.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    connection_options={"path": "s3://s3path"},
    format="csv",
    format_options={
        "quoteChar": -1,
    },
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
dataFrame.write\
    .format("csv")\
    .option("quote", None)\
    .mode("append")\
    .save("s3://s3path")
```

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

在本示例中，请使用 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 方法。

```
// Example: Write CSV to S3
// For show, customize how we write string type values. Set quoteChar to -1 so our values are not quoted.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    glueContext.getSinkWithFormat(
        connectionType="s3",
        options=JsonOptions("""{"path": "s3://s3path"}"""),
        format="csv"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

您还可以使用脚本（`org.apache.spark.sql.DataFrame`）中的 DataFrames。

```
dataFrame.write
    .format("csv")
    .option("quote", null)
    .mode("Append")
    .save("s3://s3path")
```

------

## CSV 配置参考
<a name="aws-glue-programming-etl-format-csv-reference"></a>

您可以在 AWS Glue 库指定 `format="csv"` 的任何位置使用以下 `format_options`：
+ `separator` – 指定分隔符。默认值为逗号，但也可以指定任何其他字符。
  + **类型：**文本，**默认值：**`","`
+ `escaper` – 指定要用于转义的字符。此选项仅在读取 CSV 文件而非写入时使用。如果启用，则按原样使用紧跟其后的字符，一小组已知的转义符（`\n`、`\r`、`\t` 和 `\0`）除外。
  + **类型：**文本，**默认值：**无
+ `quoteChar` – 指定要用于引用的字符。默认值为双引号。将这设置为 `-1` 可完全关闭引用。
  + **类型：**文本，**默认值：**`'"'`
+ `multiLine` – 指定单个记录能否跨越多行。当字段包含带引号的换行符时，会出现此选项。如果有记录跨越多个行，您必须将此选项设置为 `True`。启用 `multiLine` 可能会降低性能，因为它在解析时需要更加谨慎的文件拆分。
  + **类型：**布尔值，**默认值：**`false`
+ `withHeader` – 指定是否将第一行视为标头。可以在 `DynamicFrameReader` 类中使用此选项。
  + **类型：**布尔值，**默认值：**`false`
+ `writeHeader` – 指定是否将标头写入输出。可以在 `DynamicFrameWriter` 类中使用此选项。
  + **类型：**布尔值，**默认值：**`true`
+ `skipFirst` – 指定是否跳过第一个数据行。
  + **类型：**布尔值，**默认值：**`false`
+ `optimizePerformance` – 指定是否使用高级 SIMD CSV 读取器以及基于 Apache Arrow 的列式内存格式。仅适用于 AWS Glue 3.0\$1。
  + **类型：**布尔值，**默认值：**`false`
+ `strictCheckForQuoting` - 在编写 CSV 时，Glue 可能会在其解释为字符串的值中添加引号。这样做是为了防止写出的内容出现模棱两可之处。为了节省决定写入什么的时间，Glue 可能会在某些不需要引号的情况下进行引用。启用严格检查将执行更密集的计算，并且只有在绝对必要时才会引用。仅适用于 AWS Glue 3.0\$1。
  + **类型：**布尔值，**默认值：**`false`

## 使用向量化 SIMD CSV 读取器优化读取性能
<a name="aws-glue-programming-etl-format-simd-csv-reader"></a>

AWS Glue 3.0 版添加了经过优化的 CSV 读取器，与基于行的 CSV 读取器相比，它可以显著提高整体任务性能。

 优化的读取器：
+ 使用 CPU SIMD 指令从磁盘读取
+ 立即以列格式（Apache Arrow）将记录写入内存 
+ 将记录分成几批

这样可以节省日后对记录进行批处理或转换为列格式时的处理时间。例如，更改架构或按列检索数据时。

要使用优化的读取器，请将在 `format_options` 或表属性中将 `"optimizePerformance"` 设置为 `true`。

```
glueContext.create_dynamic_frame.from_options(
    frame = datasource1,
    connection_type = "s3", 
    connection_options = {"paths": ["s3://s3path"]}, 
    format = "csv", 
    format_options={
        "optimizePerformance": True, 
        "separator": ","
        }, 
    transformation_ctx = "datasink2")
```

**矢量化 CSV 读取器的限制**  
请注意向量化 CSV 读取器的以下限制：
+ 它不支持 `multiLine` 和 `escaper` 格式选项。它使用默认双引号字符 `'"'` 的 `escaper`。设置这些选项后，AWS Glue 会自动回退使用基于行的 CSV 读取器。
+ 它不支持创建具有 [ChoiceType](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-crawler-pyspark-extensions-types.html#aws-glue-api-crawler-pyspark-extensions-types-awsglue-choicetype) 的 DynamicFrame。
+ 它不支持创建具有[错误记录](https://docs.aws.amazon.com/glue/latest/dg/glue-etl-scala-apis-glue-dynamicframe-class.html#glue-etl-scala-apis-glue-dynamicframe-class-defs-errorsAsDynamicFrame)的 DynamicFrame。
+ 它不支持读取带多字节字符（如日语或中文字符）的 CSV 文件。

# 在 AWS Glue 中使用 Parquet 格式
<a name="aws-glue-programming-etl-format-parquet-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以 Parquet 数据格式存储或传输，本文档将向您介绍供您使用 AWS Glue 中的数据的可用功能。

AWS Glue 支持使用 Parquet 格式。此格式是一种以性能为导向、基于列的数据格式。有关标准颁发机构对此格式的简介，请参阅 [Apache Parquet Documentation Overview](https://parquet.apache.org/docs/overview/)（Apache Parquet 文档概述）。

您可以使用 AWS Glue 从 Amazon S3 和流式处理媒体源读取 Parquet 文件，以及将 Parquet 文件写入 Amazon S3。您可以读取并写入包含 S3 中的 Parquet 文件的 `bzip` 和 `gzip` 存档。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。

下表显示了哪些常用 AWS Glue 功能支持 Parquet 格式选项。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 支持 | 支持 | 不支持 | 支持\$1 | 

\$1 在 AWS Glue 版本 1.0\$1 中受支持

## 示例：从 S3 读取 Parquet 文件或文件夹
<a name="aws-glue-programming-etl-format-parquet-read"></a>

**先决条件：**您将需要至您想要读取的 Parquet 文件或文件夹的 S3 路径（`s3path`）。

 **配置：**在函数选项中，请指定 `format="parquet"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。

您可以在 `connection_options` 中配置读取器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。

 您可以配置读取器如何解释 `format_options` 中的 Parquet 文件。有关详细信息，请参阅 [Parquet 配置参考](#aws-glue-programming-etl-format-parquet-reference)。

以下 AWS Glue ETL 脚本显示了从 S3 读取 Parquet 文件或文件夹的过程：

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
# Example: Read Parquet from S3

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type = "s3", 
    connection_options = {"paths": ["s3://s3path/"]}, 
    format = "parquet"
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
dataFrame = spark.read.parquet("s3://s3path/")
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 方法。

```
// Example: Read Parquet from S3

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="parquet",
      options=JsonOptions("""{"paths": ["s3://s3path"]}""")
    ).getDynamicFrame()
  }
}
```

您还可以使用脚本（`org.apache.spark.sql.DataFrame`）中的 DataFrames。

```
spark.read.parquet("s3://s3path/")
```

------

## 示例：将 Parquet 文件和文件夹写入 S3
<a name="aws-glue-programming-etl-format-parquet-write"></a>

**先决条件：**您将需要一个初始化的 DataFrame（`dataFrame`）或 DynamicFrame（`dynamicFrame`）。您还需要预期 S3 输出路径 `s3path`。

 **配置：**在函数选项中，请指定 `format="parquet"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。

您可以在 `connection_options` 中进一步修改编写器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。您可以配置自己的操作在 `format_options` 中写入文件的内容的方式。有关详细信息，请参阅 [Parquet 配置参考](#aws-glue-programming-etl-format-parquet-reference)。

以下 AWS Glue ETL 脚本显示了将 Parquet 文件和文件夹写入 S3 的过程。

我们通过 `useGlueParquetWriter` 配置键为自定义 Parquet 编写器提供 DynamicFrames 的性能优化。要确定此编写器是否适合您的工作负载，请参阅 [Glue Parquet 编写器](#aws-glue-programming-etl-format-glue-parquet-writer)。

------
#### [ Python ]

在本示例中，使用 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 方法。

```
# Example: Write Parquet to S3
# Consider whether useGlueParquetWriter is right for your workflow.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    format="parquet",
    connection_options={
        "path": "s3://s3path",
    },
    format_options={
        # "useGlueParquetWriter": True,
    },
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
df.write.parquet("s3://s3path/")
```

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

在本示例中，请使用 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 方法。

```
// Example: Write Parquet to S3
// Consider whether useGlueParquetWriter is right for your workflow.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    glueContext.getSinkWithFormat(
        connectionType="s3",
        options=JsonOptions("""{"path": "s3://s3path"}"""),
        format="parquet"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

您还可以使用脚本（`org.apache.spark.sql.DataFrame`）中的 DataFrames。

```
df.write.parquet("s3://s3path/")
```

------

## Parquet 配置参考
<a name="aws-glue-programming-etl-format-parquet-reference"></a>

您可以在 AWS Glue 库指定 `format="parquet"` 的任何位置使用以下 `format_options`：
+ `useGlueParquetWriter` – 指定使用具有 DynamicFrame 工作流性能优化的自定义 Parquet 编写器。有关使用情况的详细信息，请参阅 [Glue Parquet 编写器](#aws-glue-programming-etl-format-glue-parquet-writer)。
  + **类型：**布尔值，**默认值：**`false`
+ `compression` – 指定使用的压缩编解码器。值与 `org.apache.parquet.hadoop.metadata.CompressionCodecName` 完全兼容。
  + **类型：**枚举文本，**默认值：**`"snappy"`
  + 值：`"uncompressed"`、`"snappy"`、`"gzip"` 和 `"lzo"`
+ `blockSize` – 指定内存中缓冲的行组的字节大小。您可以用它来调整性能。大小应精确地划分为若干兆字节。
  + **类型：**数值，**默认值：**`134217728`
  + 默认值等于 128MB。
+ `pageSize` – 指定页面的大小（以字节为单位）。您可以用它来调整性能。页面是必须完全读取以访问单个记录的最小单位。
  + **类型：**数值，**默认值：**`1048576`
  + 默认值等于 1MB。

**注意**  
此外，基础 SparkSQL 代码所接受的任何选项均可通过 `connection_options` 映射参数传递给此格式。例如，您可以为 AWS Glue Spark 读取器设置 Spark 配置（如 [mergeSchema](https://spark.apache.org/docs/latest/sql-data-sources-parquet.html#schema-merging)），以合并所有文件的架构。

## 使用 AWS Glue Parquet 编写器优化写入性能
<a name="aws-glue-programming-etl-format-glue-parquet-writer"></a>

**注意**  
 AWS Glue Parquet 编写器以前一直通过 `glueparquet` 格式类型访问。这种访问模式已不再提倡。请改用启用了 `useGlueParquetWriter` 的 `parquet` 类型。

AWS Glue Parquet 编写器具有允许更快地写入 Parquet 文件的性能增强功能。传统编写器在写入之前计算架构。Parquet 格式不会以可快速检索的方式存储架构，因此可能需要一些时间。使用 AWS Glue Parquet 编写器时，不需要预计算的架构。在数据传入时，编写器会动态计算和修改架构。

指定 `useGlueParquetWriter` 时请注意以下限制：
+ 编写器仅支持架构发展（例如添加或删除列）但不支持更改列类型，例如使用 `ResolveChoice`。
+ 写入器不支持写入空 DataFrame，例如，写入纯架构文件。通过设置 `enableUpdateCatalog=True` 实现与 AWS Glue Data Catalog 的集成时，尝试写入空 DataFrame 不会更新数据目录。这将导致在数据目录中创建一个没有架构的表。

如果您的转换不需要这些限制，则开启 AWS Glue Parquet 编写器应该能提高性能。

# 在 AWS Glue 中使用 XML 格式
<a name="aws-glue-programming-etl-format-xml-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以 XML 数据格式存储或传输，本文档将向您介绍供您使用 AWS Glue 中的数据的可用功能。

AWS Glue 支持使用 XML 格式。此格式表示高度可配置、严格定义的数据结构，这些数据结构不是基于行或列的。XML 是高度标准化格式。有关标准颁发机构对该格式的简介，请参阅 [XML Essentials](https://www.w3.org/standards/xml/core)（XML 基础知识）。

您可以使用 AWS Glue 从 Amazon S3 以及含有 XML 文件的 `bzip` 和 `gzip` 存档中读取 XML 文件。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。

下表显示了哪些常用 AWS Glue 功能支持 XML 格式选项。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 不支持 | 不支持 | 支持 | 支持 | 

## 示例：从 S3 读取 XML
<a name="aws-glue-programming-etl-format-xml-read"></a>

 XML 读取器采用 XML 标签名称。它检查输入中带有该标签的元素以推断架构，并使用相应的值填充 DynamicFrame。AWS Glue XML 功能的行为类似于 [XML Data Source for Apache Spark](https://github.com/databricks/spark-xml)（Apache Spark 的 XML 数据来源）。通过将此阅读器与该项目的文档进行比较，您也许可以深入了解基本行为。

**先决条件：**您将需要至您想要读取的 XML 文件或文件夹以及有关您的 XML 文件的一些信息的 S3 路径（`s3path`）。您还需要您想要读取的 XML 元素的标签 `xmlTag`。

 **配置：**在函数选项中，请指定 `format="xml"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中进一步配置读取器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。在您的 `format_options` 中，请使用 `rowTag` 键指定 `xmlTag`。您可以进一步配置读取器如何解释 `format_options` 中的 XML 文件。有关详细信息，请参阅 [XML 配置参考](#aws-glue-programming-etl-format-xml-reference)。

以下 AWS Glue ETL 脚本显示了从 S3 读取 XML 文件或文件夹的过程。

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
# Example: Read XML from S3
# Set the rowTag option to configure the reader.

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="xml",
    format_options={"rowTag": "xmlTag"},
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
dataFrame = spark.read\
    .format("xml")\
    .option("rowTag", "xmlTag")\
    .load("s3://s3path")
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 操作。

```
// Example: Read XML from S3
// Set the rowTag option to configure the reader.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.sql.SparkSession

val glueContext = new GlueContext(SparkContext.getOrCreate())
val sparkSession: SparkSession = glueContext.getSparkSession

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val dynamicFrame = glueContext.getSourceWithFormat(
      formatOptions=JsonOptions("""{"rowTag": "xmlTag"}"""), 
      connectionType="s3", 
      format="xml", 
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
}
```

您还可以使用脚本（`org.apache.spark.sql.DataFrame`）中的 DataFrames。

```
val dataFrame = spark.read
  .option("rowTag", "xmlTag")
  .format("xml")
  .load("s3://s3path“)
```

------

## XML 配置参考
<a name="aws-glue-programming-etl-format-xml-reference"></a>

您可以在 AWS Glue 库指定 `format="xml"` 的任何位置使用以下 `format_options`：
+ `rowTag` – 指定文件中要视为行的 XML 标签。行标签不能自结束。
  + **类型：**文本，**必填项**
+ `encoding` – 指定字符编码。它可以是由我们的运行时环境支持的[字符集](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html)的名称或别名。我们没有对编码支持做出具体的保证，但主编码应该起作用。
  + **类型：**文本，**默认值：**`"UTF-8"`
+ `excludeAttribute` – 指定是否要排除元素中的属性。
  + **类型：**布尔值，**默认值：**`false`
+ `treatEmptyValuesAsNulls` – 指定是否将空格视为空值。
  + **类型：**布尔值，**默认值：**`false`
+ `attributePrefix` – 用于将属性与子元素文本区分开来的属性的前缀。此前缀用于字段名称。
  + **类型：**文本，**默认值：**`"_"`
+ `valueTag` – 在元素中具有没有子项的属性时用于值的标签。
  + **类型：**文本，**默认值：**`"_VALUE"`
+ `ignoreSurroundingSpaces` – 指定是否应忽略值周围的空格。
  + **类型：**布尔值，**默认值：**`false`
+ `withSchema` – 在您想要覆盖推断的架构的情况下，包含预期的架构。如果您不使用此选项，AWS Glue 会推断 XML 数据中的架构。
  + **类型：**文本，**默认值：**不适用
  + 该值应该是代表 `StructType` 的一个 JSON 对象。

## 手动指定 XML 架构
<a name="aws-glue-programming-etl-format-xml-withschema"></a>

**手动 XML 架构示例**

此示例使用 `withSchema` 格式选项来指定 XML 数据的架构。

```
from awsglue.gluetypes import *

schema = StructType([ 
  Field("id", IntegerType()),
  Field("name", StringType()),
  Field("nested", StructType([
    Field("x", IntegerType()),
    Field("y", StringType()),
    Field("z", ChoiceType([IntegerType(), StringType()]))
  ]))
])

datasource0 = create_dynamic_frame_from_options(
    connection_type, 
    connection_options={"paths": ["s3://xml_bucket/someprefix"]},
    format="xml", 
    format_options={"withSchema": json.dumps(schema.jsonValue())},
    transformation_ctx = ""
)
```

# 在 AWS Glue 中使用 Avro 格式
<a name="aws-glue-programming-etl-format-avro-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以 Avro 数据格式存储或传输，本文档将向您介绍供您使用 AWS Glue 中的数据的可用功能。

AWS Glue 支持使用 Avro 格式。此格式是一种以性能为导向、基于行的数据格式。有关标准颁发机构对此格式的简介，请参阅 [Apache Avro 1.8.2 Documentation](https://avro.apache.org/docs/1.8.2/)（Apache Avro 1.8.2 文档）。

您可以使用 AWS Glue 从 Amazon S3 和流式传输源读取 Avro 文件，以及将 Avro 文件写入 Amazon S3。您可以读取并写入包含 S3 中的 Avro 文件的 `bzip2` 和 `gzip` 存档。此外，您还可以编写包含 Avro 文件的 `deflate`、`snappy` 和 `xz` 存档。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。

下表显示了支持 Avro 格式选项的常用 AWS Glue 功能。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 支持 | 支持\$1 | 不支持 | 支持 | 

\$1受支持，但有限制。有关更多信息，请参阅 [Avro 串流源的注释和限制](add-job-streaming.md#streaming-avro-notes)。

## 示例：从 S3 读取 Avro 文件或文件夹
<a name="aws-glue-programming-etl-format-avro-read"></a>

**先决条件：**需要待读取的 Avro 文件或文件夹的 S3 路径 (`s3path`)。

**配置：**在函数选项中，请指定 `format="avro"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中配置读取器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue：[Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 中的“Data format options for ETL inputs and outputs”（ETL 输入和输出的数据格式选项）。您可以配置读取器解释 `format_options` 中的 Avro 文件的方式。有关详细信息，请参阅 [Avro Configuration Reference](#aws-glue-programming-etl-format-avro-reference)（Avro 配置参考）。

以下 AWS Glue ETL 脚本显示了从 S3 读取 Avro 文件或文件夹的过程：

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="avro"
)
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 操作。

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.sql.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="avro",
      options=JsonOptions("""{"paths": ["s3://s3path"]}""")
    ).getDynamicFrame()
  }
```

------

## 示例：将 Avro 文件和文件夹写入 Amazon S3
<a name="aws-glue-programming-etl-format-avro-write"></a>

**先决条件：**您将需要一个初始化的 DataFrame（`dataFrame`）或 DynamicFrame（`dynamicFrame`）。您还需要预期 S3 输出路径 `s3path`。

**配置：**在函数选项中，请指定 `format="avro"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中进一步修改编写器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue：[Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 中的“Data format options for ETL inputs and outputs”（ETL 输入和输出的数据格式选项）。您可以改变写入器在 `format_options` 中解释 Avro 文件的方式。有关详细信息，请参阅 [Avro Configuration Reference](#aws-glue-programming-etl-format-avro-reference)（Avro 配置参考）。

以下 AWS Glue ETL 脚本显示了将 Avro 文件或文件夹写入 Amazon S3 的过程。

------
#### [ Python ]

在本示例中，使用 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 方法。

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    format="avro",
    connection_options={
        "path": "s3://s3path"
    }
)
```

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

在本示例中，请使用 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 方法。

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    glueContext.getSinkWithFormat(
      connectionType="s3",
      options=JsonOptions("""{"path": "s3://s3path"}"""),
      format="avro"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

------

## Avro 配置参考
<a name="aws-glue-programming-etl-format-avro-reference"></a>

您可以在 AWS Glue 库指定 `format="avro"` 的任何位置使用以下 `format_options` 值：
+ `version` – 指定要支持的 Apache Avro 读取器/写入器格式的版本。默认值为“1.7”。您可以指定 `format_options={"version": “1.8”}` 以启用 Avro 逻辑类型读取和写入。有关更多信息，请参阅 [Apache Avro 1.7.7 规范](https://avro.apache.org/docs/1.7.7/spec.html)和 [Apache Avro 1.8.2 规范](https://avro.apache.org/docs/1.8.2/spec.html)。

  Apache Avro 1.8 连接器支持以下逻辑类型转换：

对于读取器：此表显示 Avro 数据类型（逻辑类型和 Avro 基元类型）与 Avro 阅读器 1.7 和 1.8 的 AWS Glue `DynamicFrame` 数据类型之间的转换。


| Avro 数据类型：逻辑类型 | Avro 数据类型：Avro 基元类型 | GlueDynamicFrame 数据类型：Avro 读取器 1.7 | GlueDynamicFrame 数据类型：Avro 读取器 1.8 | 
| --- | --- | --- | --- | 
| 十进制 | bytes | BINARY | 十进制 | 
| 十进制 | 固定 | BINARY | 十进制 | 
| 日期 | 整数 | INT | 日期 | 
| 时间（毫秒） | 整数 | INT | INT | 
| 时间（微秒） | 长整数 | LONG | LONG | 
| 时间戳（毫秒） | 长整数 | LONG | Timestamp | 
| 时间戳（微秒） | 长整数 | LONG | LONG | 
| 持续时间（不是逻辑类型） | 固定为 12 | BINARY | BINARY | 

对于写入器：此表显示 Avro 写入器 1.7 和 1.8 在 AWS Glue `DynamicFrame` 数据类型与 Avro 数据类型之间的转换。


| AWS Glue `DynamicFrame` 数据类型 | Avro 数据类型：Avro 写入器 1.7 | Avro 数据类型：Avro 写入器 1.8 | 
| --- | --- | --- | 
| 十进制 | 字符串 | decimal | 
| 日期 | 字符串 | date | 
| Timestamp | 字符串 | timestamp-micros | 

## Avro Spark DataFrame 支持
<a name="aws-glueprogramming-etl-format-avro-dataframe-support"></a>

要使用 Spark DataFrame API 中的 Avro，您需要为相应的 Spark 版本安装 Spark Avro 插件。任务中可用的 Spark 版本取决于您的 AWS Glue 版本。有关 Spark 版本的更多信息，请参阅 [AWS Glue 版本](release-notes.md)。该插件由 Apache 维护，我们不提供具体的支持保证。

在 AWS Glue 2.0 中 – 使用 2.4.3 版本的 Spark Avro 插件。您可以在 Maven Central 上找到该 JAR，请参阅 [org.apache.spark:spark-avro\$12.12:2.4.3](https://search.maven.org/artifact/org.apache.spark/spark-avro_2.12/3.1.1/jar)。

在 AWS Glue 3.0 中 – 使用3.1.1 版本的 Spark Avro 插件。您可以在 Maven Central 上找到该 JAR，请参阅 [org.apache.spark:spark-avro\$12.12:3.1.1](https://search.maven.org/artifact/org.apache.spark/spark-avro_2.12/3.1.1/jar)。

要在 AWS Glue ETL 任务中加入额外的 JAR，请使用 `--extra-jars` 任务参数。有关任务参数的更多信息，请参阅 [在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。您也可以在 AWS 管理控制台 中配置此参数。

# 在 AWS Glue 中使用 grokLog 格式
<a name="aws-glue-programming-etl-format-grokLog-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以结构松散的纯文本格式存储或传输，本文档将向您介绍供通过 Grok 模式使用 AWS Glue 中的数据时的可用功能。

AWS Glue 支持使用 Grok 模式。Grok 模式类似于正则表达式捕获组。这些组能识别纯文本文件中的字符序列模式，并为其指定类型和用途。在 AWS Glue 中，其主要用途是读取日志。有关作者对 Grok 的说明，请参阅 [Logstash Reference: Grok filter plugin](https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html)（Logstash 参考：Grok 筛选器插件）。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 不适用 | 支持 | 支持 | 不支持 | 

## grokLog 配置参考
<a name="aws-glue-programming-etl-format-groklog-reference"></a>

您可以将以下 `format_options` 值与 `format="grokLog"` 结合使用：
+ `logFormat` – 指定与日志的格式匹配的 Grok 模式。
+ `customPatterns` – 指定在此处使用的其他 Grok 模式。
+ `MISSING` – 指定用于标识缺失值的信号。默认值为 `'-'`。
+ `LineCount` – 指定每个日志记录中的行数。默认值为 `'1'`，并且目前仅支持单行记录。
+ `StrictMode` – 指定是否启用严格模式的布尔值。在严格模式下，读取器不会执行自动类型转换或恢复。默认值为 `"false"`。

# 在 AWS Glue 中使用 Ion 格式
<a name="aws-glue-programming-etl-format-ion-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以 Ion 数据格式存储或传输，本文档将向您介绍供您使用 AWS Glue 中的数据的可用功能。

AWS Glue 支持使用 Ion 格式。此格式以可互换的二进制和纯文本表示形式表示（并非基于行或列的）数据结构。有关作者对此格式的说明，请参阅 [Amazon Ion](https://amzn.github.io/ion-docs/)。(有关更多信息，请参阅 [Amazon Ion 规范](https://amzn.github.io/ion-docs/spec.html)。)

您可以使用 AWS Glue 从 Amazon S3 中读取 Ion 文件。您可以从 S3 中读取包含 Ion 文件的 `bzip` 和 `gzip` 存档。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。

下表显示了支持 Ion 格式选项的常见 AWS Glue 功能。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 不支持 | 不支持 | 支持 | 不支持 | 

## 示例：从 S3 读取 Ion 文件或文件夹
<a name="aws-glue-programming-etl-format-ion-read"></a>

**先决条件：**需要待读取的 Ion 文件或文件夹的 S3 路径 (`s3path`)。

**配置：**在函数选项中，请指定 `format="json"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中配置读取器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。

以下 AWS Glue ETL 脚本显示了从 S3 读取 Ion 文件或文件夹的过程：

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
# Example: Read ION from S3

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="ion"
)
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 操作。

```
// Example: Read ION from S3

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="ion",
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
  }
}
```

------

## Ion 配置参考
<a name="aws-glue-programming-etl-format-ion-reference"></a>

没有适用于 `format="ion"` 的 `format_options` 值。

# 在 AWS Glue 中使用 JSON 格式
<a name="aws-glue-programming-etl-format-json-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果您的数据以 JSON 数据格式存储或传输，本文档将向您介绍供您使用 AWS Glue 中的数据的可用功能。

AWS Glue 支持使用 JSON 格式。此格式表示形状一致但内容灵活且并非基于行或列的数据结构。JSON 由多个权威机构发布的平行标准定义，其中一项标准便是 ECMA-404。有关常引用的源对该格式的说明，请参阅 [Introducing JSON](https://www.json.org/)（JSON 简介）。

您可以使用 AWS Glue 从 Amazon S3 读取 JSON 文件、`bzip` 和 `gzip` 压缩 JSON 文件。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 支持 | 支持 | 支持 | 支持 | 

## 示例：从 S3 读取 JSON 文件或文件夹
<a name="aws-glue-programming-etl-format-json-read"></a>

**先决条件：**需要待读取的 JSON 文件或文件夹的 S3 路径 (`s3path`)。

**配置：**在函数选项中，请指定 `format="json"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在连接选项中进一步更改读取操作遍历 S3 的方式，请参阅 [Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)，了解详细信息。您可以配置读取器解释 `format_options` 中 JSON 文件的方式。有关详细信息，请参阅 [JSON Configuration Reference](#aws-glue-programming-etl-format-json-reference)（JSON 配置参考）。

 以下 AWS Glue ETL 脚本显示了从 S3 读取 JSON 文件或文件夹的过程：

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
# Example: Read JSON from S3
# For show, we handle a nested JSON file that we can limit with the JsonPath parameter
# For show, we also handle a JSON where a single entry spans multiple lines
# Consider whether optimizePerformance is right for your workflow.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="json",
    format_options={
        "jsonPath": "$.id",
        "multiline": True,
        # "optimizePerformance": True, -> not compatible with jsonPath, multiline
    }
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
dataFrame = spark.read\
    .option("multiline", "true")\
    .json("s3://s3path")
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 操作。

```
// Example: Read JSON from S3
// For show, we handle a nested JSON file that we can limit with the JsonPath parameter
// For show, we also handle a JSON where a single entry spans multiple lines
// Consider whether optimizePerformance is right for your workflow.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      formatOptions=JsonOptions("""{"jsonPath": "$.id", "multiline": true, "optimizePerformance":false}"""),
      connectionType="s3",
      format="json",
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
  }
}
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
val dataFrame = spark.read
    .option("multiline", "true")
    .json("s3://s3path")
```

------

## 示例：将 JSON 文件和文件夹写入 Amazon S3
<a name="aws-glue-programming-etl-format-json-write"></a>

**先决条件：**需要初始化的 DataFrame (`dataFrame`) 或 DynamicFrame (`dynamicFrame`)。您还需要预期 S3 输出路径 `s3path`。

**配置：**在函数选项中，请指定 `format="json"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中进一步修改编写器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中的 ETL 输入和输出的数据格式选项：[Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。您可以配置读取器解释 `format_options` 中的 JSON 文件的方式。有关详细信息，请参阅 [JSON Configuration Reference](#aws-glue-programming-etl-format-json-reference)（JSON 配置参考）。

以下 AWS Glue ETL 脚本显示了从 S3 写入 JSON 文件或文件夹的过程：

------
#### [ Python ]

在本示例中，使用 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 方法。

```
# Example: Write JSON to S3

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    connection_options={"path": "s3://s3path"},
    format="json"
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
df.write.json("s3://s3path/")
```

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

在本示例中，请使用 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 方法。

```
// Example: Write JSON to S3

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    glueContext.getSinkWithFormat(
        connectionType="s3",
        options=JsonOptions("""{"path": "s3://s3path"}"""),
        format="json"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
df.write.json("s3://s3path")
```

------

## JSON 配置参考
<a name="aws-glue-programming-etl-format-json-reference"></a>

您可以将以下 `format_options` 值与 `format="json"` 结合使用：
+ `jsonPath` – [JsonPath](https://github.com/json-path/JsonPath) 表达式，标识要读取到记录中的对象。当文件包含嵌套在外部数组内的记录时，此表达式尤其有用。例如，以下 JsonPath 表达式面向 JSON 对象的 `id` 字段。

  ```
  format="json", format_options={"jsonPath": "$.id"}
  ```
+ `multiline` – 指定单个记录能否跨越多行的布尔值。当字段包含带引号的换行符时，会出现此选项。如果有记录跨越多个行，您必须将此选项设置为 `"true"`。默认值为 `"false"`，它允许在分析过程中更积极地拆分文件。
+ `optimizePerformance` – 一个布尔值，用于指定是否将高级 SIMD JSON 读取器与基于 Apache Arrow 的列式内存格式结合使用。仅适用于 AWS Glue 3.0。不兼容 `multiline` 或 `jsonPath`。提供这两个选项中的任何一个都将指示 AWS Glue 回滚到标准读取器。
+ `withSchema` – 一个字符串值，以 [手动指定 XML 架构](aws-glue-programming-etl-format-xml-home.md#aws-glue-programming-etl-format-xml-withschema) 中描述的格式指定表 Schema。仅从非目录连接读取时与 `optimizePerformance` 结合使用。

## 将矢量化 SIMD JSON 读取器与 Apache Arrow 列式格式结合使用
<a name="aws-glue-programming-etl-format-simd-json-reader"></a>

AWS Glue 版本 3.0 增加了适用于 JSON 数据的矢量化读取器。与标准读取器相比，它在某些条件下的执行速度可提高 2 倍。此读取器存在一些需要用户在使用前注意的限制，详见本节的说明。

要使用优化的读取器，请将在 `format_options` 或表属性中将 `"optimizePerformance"` 设置为 True。除非从目录中读取，否则您还需要提供 `withSchema`。`withSchema` 需要有一个 [手动指定 XML 架构](aws-glue-programming-etl-format-xml-home.md#aws-glue-programming-etl-format-xml-withschema) 中描述的输入

```
// Read from S3 data source        
glueContext.create_dynamic_frame.from_options(
    connection_type = "s3", 
    connection_options = {"paths": ["s3://s3path"]}, 
    format = "json", 
    format_options={
        "optimizePerformance": True,
        "withSchema": SchemaString
        })    
 
// Read from catalog table
glueContext.create_dynamic_frame.from_catalog(
    database = database, 
    table_name = table, 
    additional_options = {
    // The vectorized reader for JSON can read your schema from a catalog table property.
        "optimizePerformance": True,
        })
```

有关在 AWS Glue 库中构建 *SchemaString* 的更多信息，请参阅 [PySpark 扩展类型](aws-glue-api-crawler-pyspark-extensions-types.md)。

**矢量化 CSV 读取器的限制**  
请注意以下限制：
+ 不支持具有嵌套对象或数组值的 JSON 元素。AWS Glue 将回滚到标准读取器（如有提供）。
+ 必须从目录或使用 `withSchema` 参数提供一个 Schema。
+ 不兼容 `multiline` 或 `jsonPath`。提供这两个选项中的任何一个都将指示 AWS Glue 回滚到标准读取器。
+ 如果提供的输入记录与输入 Schema 不一致，将会导致读取器失败。
+ 将不会创建[错误记录](https://docs.aws.amazon.com/glue/latest/dg/glue-etl-scala-apis-glue-dynamicframe-class.html#glue-etl-scala-apis-glue-dynamicframe-class-defs-errorsAsDynamicFrame)。
+ 不支持具有多字节字符（如日语或中文字符）的 JSON 文件。

# 在 AWS Glue 中使用 ORC 格式
<a name="aws-glue-programming-etl-format-orc-home"></a>

AWS Glue 从源中检索数据，并将数据写入以各种数据格式存储和传输的目标。如果数据以 ORC 数据格式存储或传输，本文档将向您介绍在 AWS Glue 中使用数据时可用的功能。

AWS Glue 支持使用 ORC 格式。此格式是一种以性能为导向、基于列的数据格式。有关标准颁发机构对该格式的简介，请参阅 [Apache Orc](https://orc.apache.org/docs/)。

您可以使用 AWS Glue 从 Amazon S3 和流式传输源读取 ORC 文件，以及将 ORC 文件写入 Amazon S3。您可以读取并写入包含 S3 中的 ORC 文件的 `bzip` 和 `gzip` 存档。请在 [S3 连接参数](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 上而非本页中讨论的配置中配置压缩行为。

下表展示了支持 ORC 格式选项的常见 AWS Glue 操作。


| 读取 | 写入 | 流式处理读取 | 对小文件进行分组 | 作业书签 | 
| --- | --- | --- | --- | --- | 
| 支持 | 支持 | 支持 | 不支持 | 支持\$1 | 

\$1 在 AWS Glue 1.0 以上版本中受支持

## 示例：从 S3 读取 ORC 文件或文件夹
<a name="aws-glue-programming-etl-format-orc-read"></a>

**先决条件：**需要待读取的 ORC 文件或文件夹的 S3 路径 (`s3path`)。

**配置：**在函数选项中，请指定 `format="orc"`。在您的 `connection_options` 中，请使用 `paths` 键指定 `s3path`。您可以在 `connection_options` 中配置读取器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue 中 ETL 的连接类型和选项：[Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)。

 以下 AWS Glue ETL 脚本展示了从 S3 读取 ORC 文件或文件夹的过程：

------
#### [ Python ]

在本示例中，使用 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 方法。

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="orc"
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
dataFrame = spark.read\
    .orc("s3://s3path")
```

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

在本示例中，使用 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 操作。

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.sql.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="orc",
      options=JsonOptions("""{"paths": ["s3://s3path"]}""")
    ).getDynamicFrame()
  }
}
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
val dataFrame = spark.read
    .orc("s3://s3path")
```

------

## 示例：将 ORC 文件和文件夹写入 S3
<a name="aws-glue-programming-etl-format-orc-write"></a>

**先决条件：**您将需要一个初始化的 DataFrame（`dataFrame`）或 DynamicFrame（`dynamicFrame`）。您还需要预期 S3 输出路径 `s3path`。

**配置：**在函数选项中，请指定 `format="orc"`。在连接选项中，使用 `paths` 密钥指定 `s3path`。您可以在 `connection_options` 中进一步修改编写器与 S3 的交互方式。有关详细信息，请参阅 AWS Glue：[Amazon S3 连接选项参考](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 中的“Data format options for ETL inputs and outputs”（ETL 输入和输出的数据格式选项）。以下代码示例展示了这个过程：

------
#### [ Python ]

在本示例中，使用 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 方法。

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    format="orc",
    connection_options={
        "path": "s3://s3path"
    }
)
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
df.write.orc("s3://s3path/")
```

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

在本示例中，请使用 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 方法。

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    glueContext.getSinkWithFormat(
      connectionType="s3",
      options=JsonOptions("""{"path": "s3://s3path"}"""),
      format="orc"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

您还可以使用脚本（`pyspark.sql.DataFrame`）中的 DataFrames。

```
df.write.orc("s3://s3path/")
```

------

## ORC 配置参考
<a name="aws-glue-programming-etl-format-orc-reference"></a>

没有适用于 `format="orc"` 的 `format_options` 值。不过，基础 SparkSQL 代码所接受的任何选项均可通过 `connection_options` 映射参数传递给它。

# 在 AWS Glue ETL 任务中使用数据湖框架
<a name="aws-glue-programming-etl-datalake-native-frameworks"></a>

开源数据湖框架简化了对存储在 Amazon S3 上的数据湖中的文件的增量数据处理。AWS Glue 3.0 及更高版本支持以下开源数据湖框架：
+ Apache Hudi
+ Linux Foundation Delta Lake
+ Apache Iceberg

我们为这些框架提供原生支持，以便您可以以交易一致的方式读取和写入存储在 Amazon S3 中的数据。无需安装单独的连接器或完成额外的配置步骤即可在 AWS Glue ETL 任务中使用这些框架。

通过 AWS Glue Data Catalog 管理数据集时，您可以使用 AWS Glue 方法读取和写入 Spark DataFrames 数据湖表。也可以使用 Spark DataFrame API 读取和写入 Amazon S3 数据。

在这段视频中，您可以了解 Apache Hudi、Apache Iceberg 和 Delta Lake 工作原理的基础知识。您将看到如何在数据湖中插入、更新和删除数据，以及每个框架的工作原理。

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


**Topics**
+ [

# 限制
](aws-glue-programming-etl-datalake-native-frameworks-limitations.md)
+ [

# 在 AWS Glue 中使用 Hudi 框架
](aws-glue-programming-etl-format-hudi.md)
+ [

# 在 AWS Glue 中使用 Delta Lake 框架
](aws-glue-programming-etl-format-delta-lake.md)
+ [

# 在 AWS Glue 中使用 Iceberg 框架
](aws-glue-programming-etl-format-iceberg.md)

# 限制
<a name="aws-glue-programming-etl-datalake-native-frameworks-limitations"></a>

在数据湖框架与 AWS Glue 配合使用之前，请考虑以下限制。
+ 以下 AWS Glue `GlueContext` DynamicFrame 方法不支持读取和写入数据湖框架表。请改用 `GlueContext` DataFrame 方法或 Spark DataFrame API。
  + `create_dynamic_frame.from_catalog`
  + `write_dynamic_frame.from_catalog`
  + `getDynamicFrame`
  + `writeDynamicFrame`
+ 以下 `GlueContext` DataFrame 方法支持 Lake Formation 权限控制：
  + `create_data_frame.from_catalog`
  + `write_data_frame.from_catalog`
  + `getDataFrame`
  + `writeDataFrame`
+ 不支持[对小文件进行分组](grouping-input-files.md)。
+ 不支持[作业书签](monitor-continuations.md)。
+ Apache Hudi 0.10.1 for AWS Glue 3.0 不支持 Read (MoR) 表上的 Hudi Merge。
+ `ALTER TABLE … RENAME TO` 不适用于 Apache Iceberg 0.13.1 for AWS Glue 3.0。

## 有关由 Lake Formation 权限管理的数据湖格式表的限制
<a name="w2aac67c11c24c11c31c17b7"></a>

数据湖格式通过 Lake Formation 权限与 AWS Glue ETL 集成。不支持使用 `create_dynamic_frame` 创建 DynamicFrame。有关更多信息，请参阅以下示例：
+ [示例：读取和写入具有 Lake Formation 权限控制的 Iceberg 表](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-iceberg.html#aws-glue-programming-etl-format-iceberg-read-write-lake-formation-tables)
+ [示例：读取和写入具有 Lake Formation 权限控制的 Hudi 表](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-hudi.html#aws-glue-programming-etl-format-hudi-read-write-lake-formation-tables)
+ [示例：读取和写入具有 Lake Formation 权限控制的 Delta Lake 表](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-delta-lake.html#aws-glue-programming-etl-format-delta-lake-read-write-lake-formation-tables)

**注意**  
仅在 AWS Glue 版本 4.0 中支持通过适用于 Apache Hudi、Apache Iceberg 和 Delta Lake 的 Lake Formation 权限与 AWS Glue ETL 集成。

Apache Iceberg 通过 Lake Formation 权限与 AWS Glue ETL 集成的效果最好。它支持几乎所有操作，包括支持 SQL。

Hudi 支持除管理操作之外的大多数基本操作。这是因为这些选项通常通过写入 DataFrame 来完成，并通过 `additional_options` 指定。由于不支持 SparkSQL，因此需要使用 AWS Glue API 来为您的操作创建 DataFrame。

Delta Lake 仅支持读取、附加和覆盖表数据。Delta Lake 需要使用自己的库才能执行更新等各种任务。

由 Lake Formation 权限管理的 Iceberg 表不支持以下功能。
+ 使用 ETL AWS Glue 进行压缩
+ 通过 AWS Glue ETL 支持 Spark SQL

由 Lake Formation 权限管理的 Hudi 表存在以下限制：
+ 移除孤立文件

由 Lake Formation 权限管理的 Delta Lake 表存在以下限制：
+ 除在 Delta Lake 表中插入和读取数据的所有其他功能。

# 在 AWS Glue 中使用 Hudi 框架
<a name="aws-glue-programming-etl-format-hudi"></a>

AWS Glue 3.0 及更高版本支持数据湖的 Apache Hudi 框架。Hudi 是一个开源数据湖存储框架，简化增量数据处理和数据管道开发。本主题涵盖了在 Hudi 表中传输或存储数据时，在 AWS Glue 中使用数据的可用功能。要了解有关 Hudi 的更多信息，请参阅 [Apache Hudi 官方文档](https://hudi.apache.org/docs/overview/)。

您可以使用 AWS Glue 对 Amazon S3 中的 Hudi 表执行读写操作，也可以使用 AWS Glue 数据目录处理 Hudi 表。还支持其他操作，包括插入、更新和所有 [Apache Spark 操作](https://hudi.apache.org/docs/quick-start-guide/)。

**注意**  
AWS Glue 5.0 中的 Apache Hudi 0.15.0 实现会在内部回退 [HUDI-7001](https://github.com/apache/hudi/pull/9936) 变更。如果记录密钥由单个字段组成，则不会出现与复杂键生成相关的回归问题。不过，这种行为与 OSS Apache Hudi 0.15.0 不同。  
Apache Hudi 0.10.1 for AWS Glue 3.0 不支持 Read（MoR）表上的 Hudi Merge。

下表列出了 AWS Glue 每个版本中包含的 Hudi 版本。


****  

| AWS Glue 版本 | 支持的 Hudi 版本 | 
| --- | --- | 
| 5.1 | 1.0.2 | 
| 5.0 | 0.15.0 | 
| 4.0 | 0.12.1 | 
| 3.0 | 0.10.1 | 

要了解有关 AWS Glue 支持的数据湖框架的更多信息，请参阅[在 AWS Glue ETL 任务中使用数据湖框架](aws-glue-programming-etl-datalake-native-frameworks.md)。

## 启用 Hudi
<a name="aws-glue-programming-etl-format-hudi-enable"></a>

要为 AWS Glue 启用 Hudi，请完成以下任务：
+ 指定 `hudi` 作为 `--datalake-formats` 作业参数的值。有关更多信息，请参阅 [在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。
+ `--conf` 为 Glue 作业创建一个名为 AWS 的密钥，并将其设置为以下值。或者，您可以在脚本中使用 `SparkConf` 设置以下配置。这些设置有助于 Apache Spark 正确处理 Hudi 表。

  ```
  spark.serializer=org.apache.spark.serializer.KryoSerializer
  ```
+ AWS Glue 4.0 默认为 Hudi 表启用了 Lake Formation 权限支持。无需额外配置即可读取/写入注册到 Lake Formation 的 Hudi 表。AWS Glue 作业 IAM 角色必须具有 SELECT 权限才能读取已注册的 Hudi 表。AWS Glue 作业 IAM 角色必须具有 SUPER 权限才能写入已注册的 Hudi 表。要了解有关管理 Lake Formation 权限的更多信息，请参阅 [Granting and revoking permissions on Data Catalog resources](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)。

**使用不同的 Hudi 版本**

要使用 AWS Glue 不支持的 Hudi 版本，请使用 `--extra-jars` 作业参数指定您自己的 Hudi JAR 文件。请勿使用 `hudi` 作为 `--datalake-formats` 作业参数的值。如果使用 AWS Glue 5.0 或更高版本，则必须设置 `--user-jars-first true` 作业参数。

## 示例：将 Hudi 表写入 Amazon S3 并将其注册到 AWS Glue 数据目录中
<a name="aws-glue-programming-etl-format-hudi-write"></a>

以下示例脚本脚本演示了如何将 Hudi 表写入 Amazon S3，并将该表注册到 AWS Glue 数据目录。该示例使用 Hudi [Hive 同步工具](https://hudi.apache.org/docs/syncing_metastore/)来注册该表。

**注意**  
此示例要求您设置 `--enable-glue-datacatalog` 作业参数，才能将 AWS Glue Data Catalog 用作 Apache Spark Hive 元存储。要了解更多信息，请参阅[在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。

------
#### [ Python ]

```
# Example: Create a Hudi table from a DataFrame 
# and register the table to Glue Data Catalog

additional_options={
    "hoodie.table.name": "<your_table_name>",
    "hoodie.database.name": "<your_database_name>",
    "hoodie.datasource.write.storage.type": "COPY_ON_WRITE",
    "hoodie.datasource.write.operation": "upsert",
    "hoodie.datasource.write.recordkey.field": "<your_recordkey_field>",
    "hoodie.datasource.write.precombine.field": "<your_precombine_field>",
    "hoodie.datasource.write.partitionpath.field": "<your_partitionkey_field>",
    "hoodie.datasource.write.hive_style_partitioning": "true",
    "hoodie.datasource.hive_sync.enable": "true",
    "hoodie.datasource.hive_sync.database": "<your_database_name>",
    "hoodie.datasource.hive_sync.table": "<your_table_name>",
    "hoodie.datasource.hive_sync.partition_fields": "<your_partitionkey_field>",
    "hoodie.datasource.hive_sync.partition_extractor_class": "org.apache.hudi.hive.MultiPartKeysValueExtractor",
    "hoodie.datasource.hive_sync.use_jdbc": "false",
    "hoodie.datasource.hive_sync.mode": "hms",
    "path": "s3://<s3Path/>"
}

dataFrame.write.format("hudi") \
    .options(**additional_options) \
    .mode("overwrite") \
    .save()
```

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

```
// Example: Example: Create a Hudi table from a DataFrame
// and register the table to Glue Data Catalog

val additionalOptions = Map(
  "hoodie.table.name" -> "<your_table_name>",
  "hoodie.database.name" -> "<your_database_name>",
  "hoodie.datasource.write.storage.type" -> "COPY_ON_WRITE",
  "hoodie.datasource.write.operation" -> "upsert",
  "hoodie.datasource.write.recordkey.field" -> "<your_recordkey_field>",
  "hoodie.datasource.write.precombine.field" -> "<your_precombine_field>",
  "hoodie.datasource.write.partitionpath.field" -> "<your_partitionkey_field>",
  "hoodie.datasource.write.hive_style_partitioning" -> "true",
  "hoodie.datasource.hive_sync.enable" -> "true",
  "hoodie.datasource.hive_sync.database" -> "<your_database_name>",
  "hoodie.datasource.hive_sync.table" -> "<your_table_name>",
  "hoodie.datasource.hive_sync.partition_fields" -> "<your_partitionkey_field>",
  "hoodie.datasource.hive_sync.partition_extractor_class" -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
  "hoodie.datasource.hive_sync.use_jdbc" -> "false",
  "hoodie.datasource.hive_sync.mode" -> "hms",
  "path" -> "s3://<s3Path/>")

dataFrame.write.format("hudi")
  .options(additionalOptions)
  .mode("append")
  .save()
```

------

## 示例：使用 AWS Glue Data Catalog 从 Amazon S3 读取 Hudi 表
<a name="aws-glue-programming-etl-format-hudi-read"></a>

此示例从 Amazon S3 读取您在 [示例：将 Hudi 表写入 Amazon S3 并将其注册到 AWS Glue 数据目录中](#aws-glue-programming-etl-format-hudi-write) 中创建的 Hudi 表。

**注意**  
此示例要求您设置 `--enable-glue-datacatalog` 任务参数，才能将 AWS Glue Data Catalog 用作 Apache Spark Hive 元存储。要了解更多信息，请参阅[在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。

------
#### [ Python ]

在本示例中，使用 `GlueContext.create\$1data\$1frame.from\$1catalog()` 方法。

```
# Example: Read a Hudi table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

dataFrame = glueContext.create_data_frame.from_catalog(
    database = "<your_database_name>",
    table_name = "<your_table_name>"
)
```

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

在本示例中，使用 [getCatalogSource](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSource) 方法。

```
// Example: Read a Hudi table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    val dataFrame = glueContext.getCatalogSource(
      database = "<your_database_name>",
      tableName = "<your_table_name>"
    ).getDataFrame()
  }
}
```

------

## 示例：更新 `DataFrame` 并将其插入到 Amazon S3 的 Hudi 表中
<a name="aws-glue-programming-etl-format-hudi-update-insert"></a>

此示例使用 AWS Glue Data Catalog 将 DataFrame 插入到您在 [示例：将 Hudi 表写入 Amazon S3 并将其注册到 AWS Glue 数据目录中](#aws-glue-programming-etl-format-hudi-write) 中创建的 Hudi 表中。

**注意**  
此示例要求您设置 `--enable-glue-datacatalog` 任务参数，才能将 AWS Glue Data Catalog 用作 Apache Spark Hive 元存储。要了解更多信息，请参阅[在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。

------
#### [ Python ]

在本示例中，使用 `GlueContext.write\$1data\$1frame.from\$1catalog()` 方法。

```
# Example: Upsert a Hudi table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

glueContext.write_data_frame.from_catalog(
    frame = dataFrame,
    database = "<your_database_name>",
    table_name = "<your_table_name>",
    additional_options={
        "hoodie.table.name": "<your_table_name>",
        "hoodie.database.name": "<your_database_name>",
        "hoodie.datasource.write.storage.type": "COPY_ON_WRITE",
        "hoodie.datasource.write.operation": "upsert",
        "hoodie.datasource.write.recordkey.field": "<your_recordkey_field>",
        "hoodie.datasource.write.precombine.field": "<your_precombine_field>",
        "hoodie.datasource.write.partitionpath.field": "<your_partitionkey_field>",
        "hoodie.datasource.write.hive_style_partitioning": "true",
        "hoodie.datasource.hive_sync.enable": "true",
        "hoodie.datasource.hive_sync.database": "<your_database_name>",
        "hoodie.datasource.hive_sync.table": "<your_table_name>",
        "hoodie.datasource.hive_sync.partition_fields": "<your_partitionkey_field>",
        "hoodie.datasource.hive_sync.partition_extractor_class": "org.apache.hudi.hive.MultiPartKeysValueExtractor",
        "hoodie.datasource.hive_sync.use_jdbc": "false",
        "hoodie.datasource.hive_sync.mode": "hms"
    }
)
```

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

在本示例中，使用 [getCatalogSink](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSink) 方法。

```
// Example: Upsert a Hudi table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.JsonOptions
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
      additionalOptions = JsonOptions(Map(
        "hoodie.table.name" -> "<your_table_name>",
        "hoodie.database.name" -> "<your_database_name>",
        "hoodie.datasource.write.storage.type" -> "COPY_ON_WRITE",
        "hoodie.datasource.write.operation" -> "upsert",
        "hoodie.datasource.write.recordkey.field" -> "<your_recordkey_field>",
        "hoodie.datasource.write.precombine.field" -> "<your_precombine_field>",
        "hoodie.datasource.write.partitionpath.field" -> "<your_partitionkey_field>",
        "hoodie.datasource.write.hive_style_partitioning" -> "true",
        "hoodie.datasource.hive_sync.enable" -> "true",
        "hoodie.datasource.hive_sync.database" -> "<your_database_name>",
        "hoodie.datasource.hive_sync.table" -> "<your_table_name>",
        "hoodie.datasource.hive_sync.partition_fields" -> "<your_partitionkey_field>",
        "hoodie.datasource.hive_sync.partition_extractor_class" -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
        "hoodie.datasource.hive_sync.use_jdbc" -> "false",
        "hoodie.datasource.hive_sync.mode" -> "hms"
      )))
      .writeDataFrame(dataFrame, glueContext)
  }
}
```

------

## 示例：使用 Spark 从 Amazon S3 读取 Hudi 表
<a name="aws-glue-programming-etl-format-hudi-read-spark"></a>

此示例使用 Spark DataFrame API 从 Amazon S3 读取 Hudi 表。

------
#### [ Python ]

```
# Example: Read a Hudi table from S3 using a Spark DataFrame

dataFrame = spark.read.format("hudi").load("s3://<s3path/>")
```

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

```
// Example: Read a Hudi table from S3 using a Spark DataFrame

val dataFrame = spark.read.format("hudi").load("s3://<s3path/>")
```

------

## 示例：使用 Spark 向 Amazon S3 写入 Hudi 表
<a name="aws-glue-programming-etl-format-hudi-write-spark"></a>

示例：使用 Spark 向 Amazon S3 写入 Hudi 表

------
#### [ Python ]

```
# Example: Write a Hudi table to S3 using a Spark DataFrame

dataFrame.write.format("hudi") \
    .options(**additional_options) \
    .mode("overwrite") \
    .save("s3://<s3Path/>)
```

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

```
// Example: Write a Hudi table to S3 using a Spark DataFrame

dataFrame.write.format("hudi")
  .options(additionalOptions)
  .mode("overwrite")
  .save("s3://<s3path/>")
```

------

## 示例：读取和写入具有 Lake Formation 权限控制的 Hudi 表
<a name="aws-glue-programming-etl-format-hudi-read-write-lake-formation-tables"></a>

此示例将读取和写入一个具有 Lake Formation 权限控制的 Hudi 表。

1. 创建一个 Hudi 表并将其注册到 Lake Formation。

   1. 要启用 Lake Formation 权限控制，您首先需要将表的 Amazon S3 路径注册到 Lake Formation。有关更多信息，请参阅 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)（注册 Amazon S3 位置）。您可以通过 Lake Formation 控制台或使用 AWS CLI 进行注册：

      ```
      aws lakeformation register-resource --resource-arn arn:aws:s3:::<s3-bucket>/<s3-folder> --use-service-linked-role --region <REGION>
      ```

      注册了 Amazon S3 位置后，对于任何指向该位置（或其任何子位置）的 AWS Glue 表，`GetTable` 调用中的 `IsRegisteredWithLakeFormation` 参数都将返回值 true。

   1. 创建一个指向通过 Spark dataframe API 注册的 Amazon S3 路径的 Hudi 表：

      ```
      hudi_options = {
          'hoodie.table.name': table_name,
          'hoodie.database.name': database_name,
          'hoodie.datasource.write.storage.type': 'COPY_ON_WRITE',
          'hoodie.datasource.write.recordkey.field': 'product_id',
          'hoodie.datasource.write.table.name': table_name,
          'hoodie.datasource.write.operation': 'upsert',
          'hoodie.datasource.write.precombine.field': 'updated_at',
          'hoodie.datasource.write.hive_style_partitioning': 'true',
          'hoodie.upsert.shuffle.parallelism': 2,
          'hoodie.insert.shuffle.parallelism': 2,
          'path': <S3_TABLE_LOCATION>,
          'hoodie.datasource.hive_sync.enable': 'true',
          'hoodie.datasource.hive_sync.database': database_name,
          'hoodie.datasource.hive_sync.table': table_name,
          'hoodie.datasource.hive_sync.use_jdbc': 'false',
          'hoodie.datasource.hive_sync.mode': 'hms'
      }
      
      df_products.write.format("hudi")  \
          .options(**hudi_options)  \
          .mode("overwrite")  \
          .save()
      ```

1. 向 AWS Glue 作业 IAM 角色授予 Lake Formation 权限。您可以通过 Lake Formation 控制台授予权限，也可以使用 AWS CLI 授予权限。有关更多信息，请参阅 [Granting table permissions using the Lake Formation console and the named resource method](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html)。

1.  读取注册到 Lake Formation 的 Hudi 表。代码与读取未注册的 Hudi 表相同。请注意，AWS Glue 作业 IAM 角色需要具有 SELECT 权限才能成功读取。

   ```
    val dataFrame = glueContext.getCatalogSource(
         database = "<your_database_name>",
         tableName = "<your_table_name>"
       ).getDataFrame()
   ```

1. 写入注册到 Lake Formation 的 Hudi 表。代码与写入未注册的 Hudi 表相同。请注意，AWS Glue 作业 IAM 角色需要具有 SUPER 权限才能成功写入。

   ```
   glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
         additionalOptions = JsonOptions(Map(
           "hoodie.table.name" -> "<your_table_name>",
           "hoodie.database.name" -> "<your_database_name>",
           "hoodie.datasource.write.storage.type" -> "COPY_ON_WRITE",
           "hoodie.datasource.write.operation" -> "<write_operation>",
           "hoodie.datasource.write.recordkey.field" -> "<your_recordkey_field>",
           "hoodie.datasource.write.precombine.field" -> "<your_precombine_field>",
           "hoodie.datasource.write.partitionpath.field" -> "<your_partitionkey_field>",
           "hoodie.datasource.write.hive_style_partitioning" -> "true",
           "hoodie.datasource.hive_sync.enable" -> "true",
           "hoodie.datasource.hive_sync.database" -> "<your_database_name>",
           "hoodie.datasource.hive_sync.table" -> "<your_table_name>",
           "hoodie.datasource.hive_sync.partition_fields" -> "<your_partitionkey_field>",
           "hoodie.datasource.hive_sync.partition_extractor_class" -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
           "hoodie.datasource.hive_sync.use_jdbc" -> "false",
           "hoodie.datasource.hive_sync.mode" -> "hms"
         )))
         .writeDataFrame(dataFrame, glueContext)
   ```

# 在 AWS Glue 中使用 Delta Lake 框架
<a name="aws-glue-programming-etl-format-delta-lake"></a>

AWS Glue 3.0 及更高版本支持 Linux Foundation Delta Lake 框架。Delta Lake 是一个开源数据湖存储框架，可帮助您执行 ACID 交易、扩展元数据处理以及统一流式和批处理数据处理。本主题涵盖了在 Delta Lake 表中传输或存储数据时，在 AWS Glue 中使用数据的可用功能。要了解有关 Delta Lake 的更多信息，请参阅 [Delta Lake 官方文档](https://docs.delta.io/latest/delta-intro.html)。

您可以使用 AWS Glue 对 Amazon S3 中的 Delta Lake 表执行读写操作，也可以使用 AWS Glue 数据目录处理 Delta Lake 表。还支持插入、更新和[表批量读取和写入](https://docs.delta.io/0.7.0/api/python/index.html)等其他操作。使用 Delta Lake 表时，也可以选择使用 Delta Lake Python 库中的方法，例如 `DeltaTable.forPath`。有关 Delta Lake Python 库的更多信息，请参阅 Delta Lake 的 Python 文档页面。

下表列出了 AWS Glue 每个版本中包含的 Delta Lake 版本。


****  

| AWS Glue 版本 | 支持的 Delta Lake 版本 | 
| --- | --- | 
| 5.1 | 3.3.2 | 
| 5.0 | 3.3.0 | 
| 4.0 | 2.1.0 | 
| 3.0 | 1.0.0 | 

要了解有关 AWS Glue 支持的数据湖框架的更多信息，请参阅[在 AWS Glue ETL 任务中使用数据湖框架](aws-glue-programming-etl-datalake-native-frameworks.md)。

## 为 AWS Glue 启用 Delta Lake
<a name="aws-glue-programming-etl-format-delta-lake-enable"></a>

要为 AWS Glue 启用 Delta Lake，请完成以下任务：
+ 指定 `delta` 作为 `--datalake-formats` 作业参数的值。有关更多信息，请参阅 [在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。
+ `--conf` 为 Glue 作业创建一个名为 AWS 的密钥，并将其设置为以下值。或者，您可以在脚本中使用 `SparkConf` 设置以下配置。这些设置有助于 Apache Spark 正确处理 Delta Lake 表。

  ```
  spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension --conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog --conf spark.delta.logStore.class=org.apache.spark.sql.delta.storage.S3SingleDriverLogStore
  ```
+ AWS Glue 4.0 默认为 Delta 表启用了 Lake Formation 权限支持。无需额外配置即可读取/写入注册到 Lake Formation 的 Delta 表。AWS Glue 作业 IAM 角色必须具有 SELECT 权限才能读取已注册的 Delta 表。AWS Glue 作业 IAM 角色必须具有 SUPER 权限才能写入已注册的 Delta 表。要了解有关管理 Lake Formation 权限的更多信息，请参阅 [Granting and revoking permissions on Data Catalog resources](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)。

**使用不同的 Delta Lake 版本**

要使用 AWS Glue 不支持的 Delta Lake 版本，请使用 `--extra-jars` 作业参数指定您自己的 Delta Lake JAR 文件。请勿包含 `delta` 作为 `--datalake-formats` 作业参数的值。如果使用 AWS Glue 5.0 或更高版本，则必须设置 `--user-jars-first true` 作业参数。要在这种情况下使用 Delta Lake Python 库，必须使用 `--extra-py-files` 作业参数指定库 JAR 文件。Python 库打包在 Delta Lake JAR 文件中。

## 示例：将 Delta Lake 表写入 Amazon S3，并将其注册到 AWS Glue 数据目录
<a name="aws-glue-programming-etl-format-delta-lake-write"></a>

以下 AWS Glue ETL 脚本演示了如何将 Delta Lake 表写入 Amazon S3，并将该表注册到 AWS Glue 数据目录。

------
#### [ Python ]

```
# Example: Create a Delta Lake table from a DataFrame 
# and register the table to Glue Data Catalog

additional_options = {
    "path": "s3://<s3Path>"
}
dataFrame.write \
    .format("delta") \
    .options(**additional_options) \
    .mode("append") \
    .partitionBy("<your_partitionkey_field>") \
    .saveAsTable("<your_database_name>.<your_table_name>")
```

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

```
// Example: Example: Create a Delta Lake table from a DataFrame
// and register the table to Glue Data Catalog

val additional_options = Map(
  "path" -> "s3://<s3Path>"
)
dataFrame.write.format("delta")
  .options(additional_options)
  .mode("append")
  .partitionBy("<your_partitionkey_field>")
  .saveAsTable("<your_database_name>.<your_table_name>")
```

------

## 示例：使用 AWS Glue 数据目录从 Amazon S3 读取 Delta Lake 表
<a name="aws-glue-programming-etl-format-delta-lake-read"></a>

以下 AWS Glue ETL 脚本读取您在 [示例：将 Delta Lake 表写入 Amazon S3，并将其注册到 AWS Glue 数据目录](#aws-glue-programming-etl-format-delta-lake-write) 中创建的 Delta Lake 表。

------
#### [ Python ]

在本示例中，使用 [create\$1data\$1frame.from\$1catalog](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create-dataframe-from-catalog) 方法。

```
# Example: Read a Delta Lake table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

df = glueContext.create_data_frame.from_catalog(
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

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

在本示例中，使用 [getCatalogSource](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSource) 方法。

```
// Example: Read a Delta Lake table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val df = glueContext.getCatalogSource("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .getDataFrame()
  }
}
```

------

## 示例：使用 AWS Glue 数据目录在 Amazon S3 中将 `DataFrame` 插入 Delta Lake 表
<a name="aws-glue-programming-etl-format-delta-lake-insert"></a>

此示例将数据插入您在 [示例：将 Delta Lake 表写入 Amazon S3，并将其注册到 AWS Glue 数据目录](#aws-glue-programming-etl-format-delta-lake-write) 中创建的 Delta Lake 表。

**注意**  
此示例要求您设置 `--enable-glue-datacatalog` 任务参数，才能将 AWS Glue Data Catalog 用作 Apache Spark Hive 元存储。要了解更多信息，请参阅[在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。

------
#### [ Python ]

在本示例中，使用 [write\$1data\$1frame.from\$1catalog](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_data_frame_from_catalog) 方法。

```
# Example: Insert into a Delta Lake table in S3 using Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

glueContext.write_data_frame.from_catalog(
    frame=dataFrame,
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

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

在本示例中，使用 [getCatalogSink](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSink) 方法。

```
// Example: Insert into a Delta Lake table in S3 using Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .writeDataFrame(dataFrame, glueContext)
  }
}
```

------

## 示例：使用 Spark API 从 Amazon S3 读取 Delta Lake 表
<a name="aws-glue-programming-etl-format-delta_lake-read-spark"></a>

此示例使用 Spark API 从 Amazon S3 读取 Delta Lake 表。

------
#### [ Python ]

```
# Example: Read a Delta Lake table from S3 using a Spark DataFrame

dataFrame = spark.read.format("delta").load("s3://<s3path/>")
```

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

```
// Example: Read a Delta Lake table from S3 using a Spark DataFrame

val dataFrame = spark.read.format("delta").load("s3://<s3path/>")
```

------

## 示例：使用 Spark 向 Amazon S3 写入 Delta Lake 表
<a name="aws-glue-programming-etl-format-delta_lake-write-spark"></a>

此示例使用 Spark 向 Amazon S3 写入 Delta Lake 表。

------
#### [ Python ]

```
# Example: Write a Delta Lake table to S3 using a Spark DataFrame

dataFrame.write.format("delta") \
    .options(**additional_options) \
    .mode("overwrite") \
    .partitionBy("<your_partitionkey_field>")
    .save("s3://<s3Path>")
```

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

```
// Example: Write a Delta Lake table to S3 using a Spark DataFrame

dataFrame.write.format("delta")
  .options(additionalOptions)
  .mode("overwrite")
  .partitionBy("<your_partitionkey_field>")
  .save("s3://<s3path/>")
```

------

## 示例：读取和写入具有 Lake Formation 权限控制的 Delta Lake 表
<a name="aws-glue-programming-etl-format-delta-lake-read-write-lake-formation-tables"></a>

此示例将读取和写入一个具有 Lake Formation 权限控制的 Delta Lake 表。

1. 创建一个 Delta 表并将其注册到 Lake Formation

   1. 要启用 Lake Formation 权限控制，您首先需要将表的 Amazon S3 路径注册到 Lake Formation。有关更多信息，请参阅 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)（注册 Amazon S3 位置）。您可以通过 Lake Formation 控制台或使用 AWS CLI 进行注册：

      ```
      aws lakeformation register-resource --resource-arn arn:aws:s3:::<s3-bucket>/<s3-folder> --use-service-linked-role --region <REGION>
      ```

      注册了 Amazon S3 位置后，对于任何指向该位置（或其任何子位置）的 AWS Glue 表，`GetTable` 调用中的 `IsRegisteredWithLakeFormation` 参数都将返回值 true。

   1. 创建一个指向通过 Spark 注册的 Amazon S3 路径的 Delta 表：
**注意**  
以下示例属于 Python 示例。

      ```
      dataFrame.write \
      	.format("delta") \
      	.mode("overwrite") \
      	.partitionBy("<your_partitionkey_field>") \
      	.save("s3://<the_s3_path>")
      ```

      将数据写入 Amazon S3 后，使用 AWS Glue 爬网程序创建新的 Delta 目录表。有关更多信息，请参阅 [Introducing native Delta Lake table support with AWS Glue crawlers](https://aws.amazon.com/blogs/big-data/introducing-native-delta-lake-table-support-with-aws-glue-crawlers/)。

      您也可以通过 AWS Glue `CreateTable` API 手动创建表。

1. 向 AWS Glue 作业 IAM 角色授予 Lake Formation 权限。您可以通过 Lake Formation 控制台授予权限，也可以使用 AWS CLI 授予权限。有关更多信息，请参阅 [Granting table permissions using the Lake Formation console and the named resource method](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html)。

1.  读取注册到 Lake Formation 的 Delta 表。代码与读取未注册的 Delta 表相同。请注意，AWS Glue 作业 IAM 角色需要具有 SELECT 权限才能成功读取。

   ```
   # Example: Read a Delta Lake table from Glue Data Catalog
   
   df = glueContext.create_data_frame.from_catalog(
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

1. 写入注册到 Lake Formation 的 Delta 表。代码与写入未注册的 Delta 表相同。请注意，AWS Glue 作业 IAM 角色需要具有 SUPER 权限才能成功写入。

   默认情况下，AWS Glue 会将 `Append` 作为 saveMode 使用。您可以通过设置 `additional_options` 中的 saveMode 选项来对其进行更改。要了解 Delta 表中对 saveMode 的支持，请参阅 [Write to a table](https://docs.delta.io/latest/delta-batch.html#write-to-a-table)。

   ```
   glueContext.write_data_frame.from_catalog(
       frame=dataFrame,
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

# 在 AWS Glue 中使用 Iceberg 框架
<a name="aws-glue-programming-etl-format-iceberg"></a>

AWS Glue 3.0 及更高版本支持数据湖的 Apache Iceberg 框架。Iceberg 提供了一种高性能的表格式，其工作原理与 SQL 表类似。本主题涵盖了在 Iceberg 表中传输或存储数据时，在 AWS Glue 中使用数据的可用功能。要了解有关 Iceberg 的更多信息，请参阅 [Apache Iceberg 官方文档](https://iceberg.apache.org/docs/latest/)。

您可以使用 AWS Glue 对 Amazon S3 中的 Iceberg 表执行读写操作，也可以使用 AWS Glue 数据目录处理 Iceberg 表。还支持其他操作，包括插入和所有 [Spark 查询](https://iceberg.apache.org/docs/latest/spark-queries/) [Spark 写入](https://iceberg.apache.org/docs/latest/spark-writes/)。Iceberg 表不支持更新。

**注意**  
`ALTER TABLE … RENAME TO` 不适用于 Apache Iceberg 0.13.1 for AWS Glue 3.0。

下表列出了 AWS Glue 每个版本中包含的 Iceberg 版本。


****  

| AWS Glue 版本 | 支持 Iceberg 版本 | 
| --- | --- | 
| 5.1 | 1.10.0 | 
| 5.0 | 1.7.1 | 
| 4.0 | 1.0.0 | 
| 3.0 | 0.13.1 | 

要了解有关 AWS Glue 支持的数据湖框架的更多信息，请参阅[在 AWS Glue ETL 任务中使用数据湖框架](aws-glue-programming-etl-datalake-native-frameworks.md)。

## 启用 Iceberg 框架
<a name="aws-glue-programming-etl-format-iceberg-enable"></a>

要启用 Iceberg for AWS Glue，请完成以下任务：
+ 指定 `iceberg` 作为 `--datalake-formats` 作业参数的值。有关更多信息，请参阅 [在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。
+ `--conf` 为 Glue 作业创建一个名为 AWS 的密钥，并将其设置为以下值。或者，您可以在脚本中使用 `SparkConf` 设置以下配置。这些设置有助于 Apache Spark 正确处理 Iceberg 表。

  ```
  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.warehouse=s3://<your-warehouse-dir>/ 
  --conf spark.sql.catalog.glue_catalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog 
  --conf spark.sql.catalog.glue_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO
  ```

  如果正在读取或写入注册到 Lake Formation 的 Iceberg 表，请按照 AWS Glue 5.0 及更高版本中 [将 AWS Glue 与 AWS Lake Formation 结合使用以进行精细访问控制](security-lf-enable.md) 中的指南进行操作。在 AWS Glue 4.0 中，添加以下配置来启用 Lake Formation 支持。

  ```
  --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true
  --conf spark.sql.catalog.glue_catalog.glue.id=<table-catalog-id>
  ```

  如果您将 AWS Glue 3.0 与 Iceberg 0.13.1 一起使用，则必须设置以下附加配置才能使用 Amazon DynamoDB 锁定管理器来确保原子交易。AWSGlue 4.0 或更高版本默认使用乐观锁。有关更多信息，请参阅 Apache Iceberg 官方文档中的 [Iceberg AWS 集成](https://iceberg.apache.org/docs/latest/aws/#dynamodb-lock-manager)。

  ```
  --conf spark.sql.catalog.glue_catalog.lock-impl=org.apache.iceberg.aws.glue.DynamoLockManager 
  --conf spark.sql.catalog.glue_catalog.lock.table=<your-dynamodb-table-name>
  ```

**使用不同的 Iceberg 版本**

要使用 AWS Glue 不支持的 Iceberg 版本，请使用 `--extra-jars` 作业参数指定您自己的 Iceberg JAR 文件。请勿包含 `iceberg` 作为 `--datalake-formats` 参数的值。如果使用 AWS Glue 5.0 或更高版本，则必须设置 `--user-jars-first true` 作业参数。

**为 Iceberg 表启用加密**

**注意**  
Iceberg 表有自己的用于启用服务器端加密的机制。除了 AWS Glue 的安全配置外，您还应该启用此配置。

要在 Iceberg 表上启用服务器端加密，请查看 [Iceberg 文档](https://iceberg.apache.org/docs/latest/aws/#s3-server-side-encryption)中的指南。

**为 Iceberg 跨区域表访问添加 Spark 配置**

要通过 AWS Glue Data Catalog 和 AWS Lake Formation 为 Iceberg 跨区域表访问添加额外的 Spark 配置，请按照以下步骤操作：

1. 创建[多区域接入点](https://docs.aws.amazon.com/AmazonS3/latest/userguide/multi-region-access-point-create-examples.html)。

1. 设置以下 Spark 属性：

   ```
   -----
       --conf spark.sql.catalog.my_catalog.s3.use-arn-region-enabled=true \
       --conf spark.sql.catalog.{CATALOG}.s3.access-points.bucket1", "arn:aws:s3::<account-id>:accesspoint/<mrap-id>.mrap \
       --conf spark.sql.catalog.{CATALOG}.s3.access-points.bucket2", "arn:aws:s3::<account-id>:accesspoint/<mrap-id>.mrap
   -----
   ```

## 示例：将 Iceberg 表写入 Amazon S3 并将其注册到 AWS Glue 数据目录
<a name="aws-glue-programming-etl-format-iceberg-write"></a>

此示例脚本演示了如何将 Iceberg 表写入 Amazon S3。该示例使用 [IcebergAWS 集成](https://iceberg.apache.org/docs/latest/aws/)将表注册到 AWS Glue 数据目录。

------
#### [ Python ]

```
# Example: Create an Iceberg table from a DataFrame 
# and register the table to Glue Data Catalog

dataFrame.createOrReplaceTempView("tmp_<your_table_name>")

query = f"""
CREATE TABLE glue_catalog.<your_database_name>.<your_table_name>
USING iceberg
TBLPROPERTIES ("format-version"="2")
AS SELECT * FROM tmp_<your_table_name>
"""
spark.sql(query)
```

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

```
// Example: Example: Create an Iceberg table from a DataFrame
// and register the table to Glue Data Catalog

dataFrame.createOrReplaceTempView("tmp_<your_table_name>")

val query = """CREATE TABLE glue_catalog.<your_database_name>.<your_table_name>
USING iceberg
TBLPROPERTIES ("format-version"="2")
AS SELECT * FROM tmp_<your_table_name>
"""
spark.sql(query)
```

------

或者，您可以使用 Spark 方法将 Iceberg 表写入 Amazon S3 和 Data Catalog。

先决条件：您需要预置目录以供 Iceberg 库使用。使用 AWS Glue Data Catalog 时，AWS Glue 让这一切变得简单明了。AWS Glue Data Catalog 已预先配置为供 Spark 库作为 `glue_catalog` 使用。Data Catalog 表由 *databaseName* 和 *tableName* 标识。有关 AWS Glue Data Catalog 的更多信息，请参阅 [AWS Glue 中的数据发现和编目](catalog-and-crawler.md)。

如果您不使用 AWS Glue Data Catalog ，则需要通过 Spark API 配置目录。有关更多信息，请参阅 Iceberg 文档中的 [Spark Configuration](https://iceberg.apache.org/docs/latest/spark-configuration/)。

此示例使用 Spark 从将 Iceberg 表写入 Amazon S3 和 Data Catalog 中。

------
#### [ Python ]

```
# Example: Write an Iceberg table to S3 on the Glue Data Catalog

# Create (equivalent to CREATE TABLE AS SELECT)
dataFrame.writeTo("glue_catalog.databaseName.tableName") \
    .tableProperty("format-version", "2") \
    .create()

# Append (equivalent to INSERT INTO)
dataFrame.writeTo("glue_catalog.databaseName.tableName") \
    .tableProperty("format-version", "2") \
    .append()
```

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

```
// Example: Write an Iceberg table to S3 on the Glue Data Catalog

// Create (equivalent to CREATE TABLE AS SELECT)
dataFrame.writeTo("glue_catalog.databaseName.tableName")
    .tableProperty("format-version", "2")
    .create()

// Append (equivalent to INSERT INTO)
dataFrame.writeTo("glue_catalog.databaseName.tableName")
    .tableProperty("format-version", "2")
    .append()
```

------

## 示例：使用 AWS Glue 数据目录从 Amazon S3 读取 Iceberg 表
<a name="aws-glue-programming-etl-format-iceberg-read"></a>

此示例读取您在 [示例：将 Iceberg 表写入 Amazon S3 并将其注册到 AWS Glue 数据目录](#aws-glue-programming-etl-format-iceberg-write) 中创建的 Iceberg 表。

------
#### [ Python ]

在本示例中，使用 `GlueContext.create\$1data\$1frame.from\$1catalog()` 方法。

```
# Example: Read an Iceberg table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

df = glueContext.create_data_frame.from_catalog(
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

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

在本示例中，使用 [getCatalogSource](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSource) 方法。

```
// Example: Read an Iceberg table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val df = glueContext.getCatalogSource("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .getDataFrame()
  }
}
```

------

## 示例：使用 AWS Glue 数据目录在 Amazon S3 将 `DataFrame` 插入 Iceberg 表
<a name="aws-glue-programming-etl-format-iceberg-insert"></a>

此示例将数据插入您在 [示例：将 Iceberg 表写入 Amazon S3 并将其注册到 AWS Glue 数据目录](#aws-glue-programming-etl-format-iceberg-write) 中创建的 Iceberg 表。

**注意**  
此示例要求您设置 `--enable-glue-datacatalog` 任务参数，才能将 AWS Glue Data Catalog 用作 Apache Spark Hive 元存储。要了解更多信息，请参阅[在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。

------
#### [ Python ]

在本示例中，使用 `GlueContext.write\$1data\$1frame.from\$1catalog()` 方法。

```
# Example: Insert into an Iceberg table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

glueContext.write_data_frame.from_catalog(
    frame=dataFrame,
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

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

在本示例中，使用 [getCatalogSink](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSink) 方法。

```
// Example: Insert into an Iceberg table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .writeDataFrame(dataFrame, glueContext)
  }
}
```

------

## 示例：使用 Spark 从 Amazon S3 读取 Iceberg 表
<a name="aws-glue-programming-etl-format-iceberg-read-spark"></a>

先决条件：您需要预置目录以供 Iceberg 库使用。使用 AWS Glue Data Catalog 时，AWS Glue 让这一切变得简单明了。AWS Glue Data Catalog 已预先配置为供 Spark 库作为 `glue_catalog` 使用。Data Catalog 表由 *databaseName* 和 *tableName* 标识。有关 AWS Glue Data Catalog 的更多信息，请参阅 [AWS Glue 中的数据发现和编目](catalog-and-crawler.md)。

如果您不使用 AWS Glue Data Catalog ，则需要通过 Spark API 配置目录。有关更多信息，请参阅 Iceberg 文档中的 [Spark Configuration](https://iceberg.apache.org/docs/latest/spark-configuration/)。

此示例使用 Spark 从 Data Catalog 读取 Amazon S3 中的 Iceberg 表。

------
#### [ Python ]

```
# Example: Read an Iceberg table on S3 as a DataFrame from the Glue Data Catalog

dataFrame = spark.read.format("iceberg").load("glue_catalog.databaseName.tableName")
```

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

```
// Example: Read an Iceberg table on S3 as a DataFrame from the Glue Data Catalog

val dataFrame = spark.read.format("iceberg").load("glue_catalog.databaseName.tableName")
```

------

## 示例：读取和写入具有 Lake Formation 权限控制的 Iceberg 表
<a name="aws-glue-programming-etl-format-iceberg-read-write-lake-formation-tables"></a>

此示例将读取和写入一个具有 Lake Formation 权限控制的 Iceberg 表。

**注意**  
此示例仅适用于 AWS Glue 4.0。在 AWS Glue 5.0 及更高版本中，请按照 [将 AWS Glue 与 AWS Lake Formation 结合使用以进行精细访问控制](security-lf-enable.md) 中的指南进行操作。

1. 创建一个 Iceberg 表并将其注册到 Lake Formation：

   1. 要启用 Lake Formation 权限控制，您首先需要将表的 Amazon S3 路径注册到 Lake Formation。有关更多信息，请参阅 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)（注册 Amazon S3 位置）。您可以通过 Lake Formation 控制台或使用 AWS CLI 进行注册：

      ```
      aws lakeformation register-resource --resource-arn arn:aws:s3:::<s3-bucket>/<s3-folder> --use-service-linked-role --region <REGION>
      ```

      注册了 Amazon S3 位置后，对于任何指向该位置（或其任何子位置）的 AWS Glue 表，`GetTable` 调用中的 `IsRegisteredWithLakeFormation` 参数都将返回值 true。

   1. 创建一个指向通过 Spark SQL 注册的路径的 Iceberg 表：
**注意**  
以下示例属于 Python 示例。

      ```
      dataFrame.createOrReplaceTempView("tmp_<your_table_name>")
      
      query = f"""
      CREATE TABLE glue_catalog.<your_database_name>.<your_table_name>
      USING iceberg
      AS SELECT * FROM tmp_<your_table_name>
      """
      spark.sql(query)
      ```

      您也可以通过 AWS Glue `CreateTable` API 手动创建表。有关更多信息，请参阅 [Creating Apache Iceberg tables](https://docs.aws.amazon.com/lake-formation/latest/dg/creating-iceberg-tables.html)。
**注意**  
该 `UpdateTable` API 目前不支持 Iceberg 表格式作为操作的输入。

1. 向作业 IAM 角色授予 Lake Formation 权限。您可以通过 Lake Formation 控制台授予权限，也可以使用 AWS CLI 授予权限。有关更多信息，请参阅 https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html

1. 读取注册到 Lake Formation 的 Iceberg 表。代码与读取未注册的 Iceberg 表相同。请注意，您的 AWS Glue 作业 IAM 角色需要具有 SELECT 权限才能成功读取。

   ```
   # Example: Read an Iceberg table from the AWS Glue Data Catalog
   from awsglue.context import GlueContextfrom pyspark.context import SparkContext
   
   sc = SparkContext()
   glueContext = GlueContext(sc)
   
   df = glueContext.create_data_frame.from_catalog(
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

1. 写入注册到 Lake Formation 的 Iceberg 表。代码与写入未注册的 Iceberg 表相同。请注意，您的 AWS Glue 作业 IAM 角色需要具有 SUPER 权限才能成功写入。

   ```
   glueContext.write_data_frame.from_catalog(
       frame=dataFrame,
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

## 共享配置参考
<a name="aws-glue-programming-etl-format-shared-reference"></a>

 您可以对任何格式类型使用以下 `format_options` 值：
+ `attachFilename` - 适当格式的字符串，用作列名。如果您提供此选项，则记录的源文件名将附加到记录中。参数值将用作列名。
+ `attachTimestamp` - 适当格式的字符串，用作列名。如果您提供此选项，则记录的源文件的修改时间将附加到记录中。参数值将用作列名。

# 适用于 Spark SQL 作业的 AWS Glue 数据目录支持
<a name="aws-glue-programming-etl-glue-data-catalog-hive"></a>

AWS Glue 是一个与 Apache Hive 元存储兼容的目录。您可以配置 AWS Glue 任务和开发端点以使用数据目录作为外部 Apache Hive 元存储。随后，您可以直接对存储在数据目录中的表运行 Apache Spark SQL 查询。预设情况下，AWS Glue 动态帧与数据目录集成。但是，利用此功能，Spark SQL 任务可以开始使用数据目录作为外部 Hive 元存储。

此功能要求对 AWS Glue API 端点的网络访问权限。对于连接位于私有子网中的 AWS Glue 任务，必须配置 VPC 终端节点或 NAT 网关以提供网络访问。有关配置 VPC 终端节点的信息，请参阅 [设置对数据存储的网络访问](start-connecting.md)。要创建 NAT 网关，请参阅 *Amazon VPC 用户指南*中的 [NAT 网关](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)。

您可以通过将 `"--enable-glue-datacatalog": ""` 参数分别添加到作业参数和开发终端节点参数来配置 AWS Glue 作业和开发终端节点。传递此参数将在 Spark 中设置某些配置，使其能够访问数据目录作为外部 Hive 元存储。它还在 AWS Glue 任务或开发端点中创建的 `SparkSession` 对象中[启用 Hive 支持](https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/SparkSession.Builder.html#enableHiveSupport--)。

要启用数据目录访问，请在控制台的 **Add job** (添加任务) 或 **Add endpoint** (添加端点) 页面上，选中 **Catalog options** (目录选项) 组中的 **Use AWS Glue Data Catalog as the Hive metastore** (使用 AWS Glue 数据目录作为 Hive 元存储) 复选框。请注意，用于作业或开发终端节点的 IAM 角色应具有 `glue:CreateDatabase` 权限。在数据目录中创建一个名为“`default`”的数据库（如果该数据库不存在）。

让我们看一下如何在 Spark SQL 作业中使用此功能的示例。以下示例假定您已对 `s3://awsglue-datasets/examples/us-legislators` 中提供的美国议员数据集进行爬网。

要从 AWS Glue 数据目录中定义的表中序列化/反序列化数据，Spark SQL 需要在 Spark 任务的类路径中的 AWS Glue 数据目录中定义的格式的 [Hive SerDe](https://cwiki.apache.org/confluence/display/Hive/SerDe) 类。

某些常见格式的 SerDes 由 AWS Glue 分发。以下是这些格式的 Amazon S3 链接：
+ [JSON](https://s3.us-west-2.amazonaws.com/crawler-public/json/serde/json-serde.jar)
+ [XML](https://s3.us-west-2.amazonaws.com/crawler-public/xml/serde/hivexmlserde-1.0.5.3.jar)
+ [Grok](https://s3.us-west-2.amazonaws.com/crawler-public/grok/serde/AWSGlueHiveGrokSerDe-1.0-super.jar)

将 JSON SerDe 作为[额外的 JAR 添加到开发终端节点](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-dev-endpoint.html#aws-glue-api-dev-endpoint-DevEndpointCustomLibraries)。对于作业，您可以使用参数字段中的 `--extra-jars` 参数添加 SerDe。有关更多信息，请参阅 [在 AWS Glue 作业中使用作业参数](aws-glue-programming-etl-glue-arguments.md)。

以下是用于创建开发终端节点的示例输入 JSON，其中已为 Spark SQL 启用数据目录。

```
{
    "EndpointName": "Name",
    "RoleArn": "role_ARN",
    "PublicKey": "public_key_contents",
    "NumberOfNodes": 2,
    "Arguments": {
      "--enable-glue-datacatalog": ""
    },
    "ExtraJarsS3Path": "s3://crawler-public/json/serde/json-serde.jar"
}
```

现在，使用 Spark SQL 查询从美国议员数据集创建的表。

```
>>> spark.sql("use legislators")
DataFrame[]
>>> spark.sql("show tables").show()
+-----------+------------------+-----------+
|   database|         tableName|isTemporary|
+-----------+------------------+-----------+
|legislators|        areas_json|      false|
|legislators|    countries_json|      false|
|legislators|       events_json|      false|
|legislators|  memberships_json|      false|
|legislators|organizations_json|      false|
|legislators|      persons_json|      false|
+-----------+------------------+-----------+
>>> spark.sql("describe memberships_json").show()
+--------------------+---------+-----------------+
|            col_name|data_type|          comment|
+--------------------+---------+-----------------+
|             area_id|   string|from deserializer|
|     on_behalf_of_id|   string|from deserializer|
|     organization_id|   string|from deserializer|
|                role|   string|from deserializer|
|           person_id|   string|from deserializer|
|legislative_perio...|   string|from deserializer|
|          start_date|   string|from deserializer|
|            end_date|   string|from deserializer|
+--------------------+---------+-----------------+
```

如果作业的类路径中没有该格式的 SerDe 类，您将看到与以下内容类似的错误。

```
>>> spark.sql("describe memberships_json").show()

Caused by: MetaException(message:java.lang.ClassNotFoundException Class org.openx.data.jsonserde.JsonSerDe not found)
    at org.apache.hadoop.hive.metastore.MetaStoreUtils.getDeserializer(MetaStoreUtils.java:399)
    at org.apache.hadoop.hive.ql.metadata.Table.getDeserializerFromMetaStore(Table.java:276)
    ... 64 more
```

要仅从 `memberships` 表中查看不同的 `organization_id`s，请运行以下 SQL 查询。

```
>>> spark.sql("select distinct organization_id from memberships_json").show()
+--------------------+
|     organization_id|
+--------------------+
|d56acebe-8fdc-47b...|
|8fa6c3d2-71dc-478...|
+--------------------+
```

如果需要对动态帧执行相同操作，请运行以下操作。

```
>>> memberships = glueContext.create_dynamic_frame.from_catalog(database="legislators", table_name="memberships_json")
>>> memberships.toDF().createOrReplaceTempView("memberships")
>>> spark.sql("select distinct organization_id from memberships").show()
+--------------------+
|     organization_id|
+--------------------+
|d56acebe-8fdc-47b...|
|8fa6c3d2-71dc-478...|
+--------------------+
```

虽然 DynamicFrames 已针对 ETL 操作进行优化，但启用 Spark SQL 以直接访问数据目录提供了一种运行复杂的 SQL 语句或移植现有应用程序的简洁方法。

# 使用作业书签
<a name="programming-etl-connect-bookmarks"></a>

AWS Glue for Spark 使用作业书签来跟踪已处理的数据。有关作业书签功能及其支持的内容的摘要，请参阅 [使用作业书签跟踪已处理的数据](monitor-continuations.md)。使用书签对 AWS Glue 作业进行编程时，您可以获得可视化作业中无法获得的灵活性。
+  从 JDBC 读取时，您可以指定要用作 AWS Glue 脚本中书签键的列。
+  您可以选择将哪个 `transformation_ctx` 方法应用于每个方法调用。

*始终在脚本开头调用 `job.init` 并在脚本结尾调用 `job.commit`，并恰当配置参数*。这两个函数初始化书签服务并更新服务的状态更改。如果没有调用书签，书签将无法正常工作。

## 指定书签键
<a name="programming-etl-connect-bookmarks-columns"></a>

对于 JDBC 工作流程，书签通过将关键字段的值与已添加书签的值进行比较来跟踪您的作业已读取的行。这不是必需的，也不适用于 Amazon S3 工作流程。在没有可视化编辑器的情况下编写 AWS Glue 脚本时，您可以指定使用书签跟踪哪一列。您也可以指定多列。指定用户定义的书签键时，允许在值序列中出现间隔。

**警告**  
如果使用用户定义的书签键，则它们每个都必须严格单调递增或递减。为复合键选择其他字段时，“次要版本”或“修订编号”等概念的字段不符合此标准，因为它们的值会在整个数据集中重复使用。

您可以通过以下方式指定 `jobBookmarkKeys` 和 `jobBookmarkKeysSortOrder`：
+ `create_dynamic_frame.from_catalog` — 使用 `additional_options`。
+ `create_dynamic_frame.from_options` — 使用 `connection_options`。

## 转换上下文
<a name="monitor-continuations-implement-context"></a>

许多 AWS Glue PySpark 动态帧方法都包括一个名为 `transformation_ctx` 的可选参数，这是 ETL 运算符实例的唯一标识符。该 `transformation_ctx` 参数用于在作业书签中标识给定运算符的状态信息。具体来说，AWS Glue 使用 `transformation_ctx` 来为书签状态键建立索引。

**警告**  
`transformation_ctx` 作为键以搜索脚本中特定源的书签状态。为了使书签正常工作，您应始终让源和相关的 `transformation_ctx` 保持一致。更改源属性或重命名 `transformation_ctx` 可能会使之前的书签无效，并且基于时间戳的筛选条件可能无法产生正确的结果。

为了使作业书签正常使用，请启用作业书签参数并设置 `transformation_ctx` 参数。如果您未传入 `transformation_ctx` 参数，则不会为方法中使用的动态帧或表启用作业书签。例如，如果您有一个用于读取和连接两个 Amazon S3 源的 ETL 任务，您可能会选择仅将 `transformation_ctx` 参数传递给要启用书签的方法。如果您重置作业的作业书签，它会重置与作业相关联的所有转换，而不考虑所使用的 `transformation_ctx`。

有关 `DynamicFrameReader` 类的更多信息，请参阅[DynamicFrameReader 类](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader.md)。有关 PySpark 扩展的更多信息，请参阅 [AWS Glue PySpark 扩展参考](aws-glue-programming-python-extensions.md)。

## 示例
<a name="monitor-continuations-implement-examples"></a>

**Example**  
以下是为 Amazon S3 数据源生成的脚本的示例。使用作业书签所需的脚本部分以斜体显示。有关这些元素的更多信息，请参阅 [GlueContext 类](aws-glue-api-crawler-pyspark-extensions-glue-context.md) API 和 [DynamicFrameWriter 类](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-writer.md) API。  

```
# Sample Script
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

datasource0 = glueContext.create_dynamic_frame.from_catalog(
    database = "database",
    table_name = "relatedqueries_csv",
    transformation_ctx = "datasource0"
)

applymapping1 = ApplyMapping.apply(
    frame = datasource0,
    mappings = [("col0", "string", "name", "string"), ("col1", "string", "number", "string")],
    transformation_ctx = "applymapping1"
)

datasink2 = glueContext.write_dynamic_frame.from_options(
    frame = applymapping1,
    connection_type = "s3",
    connection_options = {"path": "s3://input_path"},
    format = "json",
    transformation_ctx = "datasink2"
)


job.commit()
```

**Example**  
以下是为 JDBC 源生成的脚本的示例。源表是一个将 `empno` 列作为主键的员工表。尽管默认情况下，如果未指定书签键，则任务会使用顺序主键作为书签键，但由于 `empno` 不一定是连续的，值中可能会有间隙，它不能作为默认书签键。因此，脚本会将 `empno` 显式指定为书签键。代码的此部分以斜体显示。  

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

datasource0 = glueContext.create_dynamic_frame.from_catalog(
    database = "hr",
    table_name = "emp",
    transformation_ctx = "datasource0",
    additional_options = {"jobBookmarkKeys":["empno"],"jobBookmarkKeysSortOrder":"asc"}
)

applymapping1 = ApplyMapping.apply(
    frame = datasource0,
    mappings = [("ename", "string", "ename", "string"), ("hrly_rate", "decimal(38,0)", "hrly_rate", "decimal(38,0)"), ("comm", "decimal(7,2)", "comm", "decimal(7,2)"), ("hiredate", "timestamp", "hiredate", "timestamp"), ("empno", "decimal(5,0)", "empno", "decimal(5,0)"), ("mgr", "decimal(5,0)", "mgr", "decimal(5,0)"), ("photo", "string", "photo", "string"), ("job", "string", "job", "string"), ("deptno", "decimal(3,0)", "deptno", "decimal(3,0)"), ("ssn", "decimal(9,0)", "ssn", "decimal(9,0)"), ("sal", "decimal(7,2)", "sal", "decimal(7,2)")],
    transformation_ctx = "applymapping1"
)

datasink2 = glueContext.write_dynamic_frame.from_options(
    frame = applymapping1,
    connection_type = "s3",
    connection_options = {"path": "s3://hr/employees"},
    format = "csv",
    transformation_ctx = "datasink2"
)

job.commit()
```

# 在 AWS Glue Studio 外部使用敏感数据检测
<a name="aws-glue-api-sensitive-data-example"></a>

 AWS Glue Studio 允许您检测敏感数据，但是，您也可以在 AWS Glue Studio 外部使用敏感数据检测功能。

 有关托管的敏感数据类型的完整列表，请参阅 [Managed data types](https://docs.aws.amazon.com/glue/latest/dg/sensitive-data-managed-data-types.html)。

## 使用 AWS 托管 PII 类型检测敏感数据
<a name="sensitive-data-managed-pii-types"></a>

 AWS Glue 在 AWS Glue ETL 任务中提供两个 API。它们是 `detect()` 和 `classifyColumns()`。

```
  detect(frame: DynamicFrame, 
      entityTypesToDetect: Seq[String], 
      outputColumnName: String = "DetectedEntities",
      detectionSensitivity: String = "LOW"): DynamicFrame

 detect(frame: DynamicFrame, 
      detectionParameters: JsonOptions,
      outputColumnName: String = "DetectedEntities",
      detectionSensitivity: String = "LOW"): DynamicFrame
      
  classifyColumns(frame: DynamicFrame, 
      entityTypesToDetect: Seq[String], 
      sampleFraction: Double = 0.1, 
      thresholdFraction: Double = 0.1,
      detectionSensitivity: String = "LOW")
```

 您可以使用 `detect()` API 来识别 AWS 托管 PII 类型和自定义实体类型。将使用检测结果自动创建一个新列。`classifyColumns()` API 将返回一个映射，其中键是列名，值是检测到的实体类型列表。`SampleFraction` 表示扫描 PII 实体时要采样的一小部分数据，而 `ThresholdFraction` 表示为了将列标识为 PII 数据而必须满足的一小部分数据。

### 行级别检测
<a name="w2aac67c11c24c19b9c11"></a>

 在示例中，该任务使用 `detect()` 和 `classifyColumns()` API 执行以下操作：
+  从 Amazon S3 存储桶读取数据并将其转换为 dynamicFrame 
+  在 dynamicFrame 中检测“电子邮件”和“信用卡”的实例 
+  返回一个 dynamicFrame，其中包含原始值和一列，其中包含每行的检测结果 
+  将返回的 dynamicFrame 写入另一个 Amazon S3 路径 

```
  import com.amazonaws.services.glue.GlueContext
  import com.amazonaws.services.glue.MappingSpec
  import com.amazonaws.services.glue.errors.CallSite
  import com.amazonaws.services.glue.util.GlueArgParser
  import com.amazonaws.services.glue.util.Job
  import com.amazonaws.services.glue.util.JsonOptions
  import org.apache.spark.SparkContext
  import scala.collection.JavaConverters._
  import com.amazonaws.services.glue.ml.EntityDetector
  
  object GlueApp {
    def main(sysArgs: Array[String]) {
      val spark: SparkContext = new SparkContext()
      val glueContext: GlueContext = new GlueContext(spark)
      val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
      Job.init(args("JOB_NAME"), glueContext, args.asJava)
      val frame= glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ","}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="AmazonS3_node1650160158526").getDynamicFrame()
  
      val frameWithDetectedPII = EntityDetector.detect(frame, Seq("EMAIL", "CREDIT_CARD"))
  
      glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput/", "partitionKeys": []}"""), transformationContext="someCtx", format="json").writeDynamicFrame(frameWithDetectedPII)
  
      Job.commit()
    }
  }
```

### 使用精细操作进行行级别检测
<a name="w2aac67c11c24c19b9c15"></a>

 示例中的作业将使用 `detect()` API 执行以下操作：
+  从 Amazon S3 存储桶读取数据并将其转换为 dynamicFrame 
+  检测 dynamicFrame 中的“USA\$1PTIN”、“ BANK\$1ACCOUNT”、“USA\$1SSN”、“USA\$1PASSPORT\$1NUMBER”和“PHONE\$1NUMBER”等敏感数据类型 
+  返回一个 dynamicFrame，其中包含修改后的遮蔽值以及一个包含每行的检测结果的列 
+  将返回的 dynamicFrame 写入另一个 Amazon S3 路径 

 与上述 `detect()` API 不同的是，这将使用精细操作来检测实体类型。有关更多信息，请参阅 [使用 `detect()` 方法所需的检测参数](#sensitive-data-detect-parameters-fine-grained-actions)。

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._
import com.amazonaws.services.glue.ml.EntityDetector

object GlueApp {
  def main(sysArgs: Array[String]) {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    val frame = glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ","}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="AmazonS3_node_source").getDynamicFrame()

    val detectionParameters = JsonOptions(
      """
        {
          "USA_DRIVING_LICENSE": [{
            "action": "PARTIAL_REDACT",
            "sourceColumns": ["Driving License"],
            "actionOptions": {
              "matchPattern": "[0-9]",
              "redactChar": "*"
            }
          }],
          "BANK_ACCOUNT": [{
            "action": "DETECT",
            "sourceColumns": ["*"]
          }],
          "USA_SSN": [{
            "action": "SHA256_HASH",
            "sourceColumns": ["SSN"]
          }],
          "IP_ADDRESS": [{
            "action": "REDACT",
            "sourceColumns": ["IP Address"],
            "actionOptions": {"redactText": "*****"}
          }],
          "PHONE_NUMBER": [{
            "action": "PARTIAL_REDACT",
            "sourceColumns": ["Phone Number"],
            "actionOptions": {
              "numLeftCharsToExclude": 1,
              "numRightCharsToExclude": 0,
              "redactChar": "*"
            }
          }]
        }
      """
    )

    val frameWithDetectedPII = EntityDetector.detect(frame, detectionParameters, "DetectedEntities", "HIGH")

    glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput/", "partitionKeys": []}"""), transformationContext="AmazonS3_node_target", format="json").writeDynamicFrame(frameWithDetectedPII)

    Job.commit()
  }
}
```

### 列级别检测
<a name="w2aac67c11c24c19b9c19"></a>

 示例中的作业将使用 `classifyColumns()` API 执行以下操作：
+  从 Amazon S3 存储桶读取数据并将其转换为 dynamicFrame 
+  在 dynamicFrame 中检测“电子邮件”和“信用卡”的实例 
+  将参数设置为对列进行 100% 采样，如果实体位于 10% 的单元格中，并且敏感性为“低”，则将其标记为已检测 
+  返回一个以列名为键，以检测到的实体类型列表为值的映射 
+  将返回的 dynamicFrame 写入另一个 Amazon S3 路径 

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._
import com.amazonaws.services.glue.DynamicFrame
import com.amazonaws.services.glue.ml.EntityDetector

object GlueApp {
  def main(sysArgs: Array[String]) {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    val frame = glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ",", "optimizePerformance": false}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="frame").getDynamicFrame()
    
    import glueContext.sparkSession.implicits._

    val detectedDataFrame = EntityDetector.classifyColumns(
        frame, 
        entityTypesToDetect = Seq("CREDIT_CARD", "PHONE_NUMBER"), 
        sampleFraction = 1.0, 
        thresholdFraction = 0.1,
        detectionSensitivity = "LOW"
    )
    val detectedDF = (detectedDataFrame).toSeq.toDF("columnName", "entityTypes")
    val DetectSensitiveData_node = DynamicFrame(detectedDF, glueContext)

    glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput", "partitionKeys": []}"""), transformationContext="someCtx", format="json").writeDynamicFrame(DetectSensitiveData_node)

    Job.commit()
  }
}
```

## 使用 AWS CustomEntityType PII 类型检测敏感数据
<a name="sensitive-data-custom-entity-PII-types"></a>

 您可以通过 AWS Studio 定义自定义实体。但是，要在 AWS Studio 外部使用此功能，必须先定义自定义实体类型，然后将定义的自定义实体类型添加到 `entityTypesToDetect` 列表。

 如果您的数据中有特定的敏感数据类型（例如“员工 ID”），则可以通过调用 `CreateCustomEntityType()` API 创建自定义实体。以下示例使用请求参数将自定义实体类型“EMPLOYEE\$1ID”定义到 `CreateCustomEntityType()` API：

```
  { 
      "name": "EMPLOYEE_ID",
      "regexString": "\d{4}-\d{3}",
      "contextWords": ["employee"]
  }
```

 然后，通过将自定义实体类型 (EMPLOYEE\$1ID) 添加到 `EntityDetector()` API，修改任务以使用新的自定义敏感数据类型：

```
  import com.amazonaws.services.glue.GlueContext
  import com.amazonaws.services.glue.MappingSpec
  import com.amazonaws.services.glue.errors.CallSite
  import com.amazonaws.services.glue.util.GlueArgParser
  import com.amazonaws.services.glue.util.Job
  import com.amazonaws.services.glue.util.JsonOptions
  import org.apache.spark.SparkContext
  import scala.collection.JavaConverters._
  import com.amazonaws.services.glue.ml.EntityDetector
  
  object GlueApp {
    def main(sysArgs: Array[String]) {
      val spark: SparkContext = new SparkContext()
      val glueContext: GlueContext = new GlueContext(spark)
      val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
      Job.init(args("JOB_NAME"), glueContext, args.asJava)
      val frame= glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ","}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="AmazonS3_node1650160158526").getDynamicFrame()
  
      val frameWithDetectedPII = EntityDetector.detect(frame, Seq("EMAIL", "CREDIT_CARD", "EMPLOYEE_ID"))
  
      glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput/", "partitionKeys": []}"""), transformationContext="someCtx", format="json").writeDynamicFrame(frameWithDetectedPII)
  
      Job.commit()
    }
  }
```

**注意**  
 如果定义的自定义敏感数据类型与现有托管实体类型的名称相同，则自定义敏感数据类型将优先并覆盖该托管实体类型的逻辑。

## 使用 `detect()` 方法所需的检测参数
<a name="sensitive-data-detect-parameters-fine-grained-actions"></a>

 此方法用于检测 DynamicFrame 中的实体。此方法将返回一个新 DataFrame，其中包含原始值以及一个具有 PII 检测元数据的附加列 outputColumnName。返回此 DynamicFrame 后可以在 AWS Glue 脚本中进行自定义遮蔽，也可以改用使用精细操作 API 的 detect() 方法。

```
detect(frame: DynamicFrame, 
       entityTypesToDetect: Seq[String], 
       outputColumnName: String = "DetectedEntities",
       detectionSensitivity: String = "LOW"): DynamicFrame
```

 参数：
+  **frame** –（类型：`DynamicFrame`）包含要处理的数据的输入 DynamicFrame。
+  **entityTypesToDetect** –（类型：`[Seq[String]`）要检测的实体类型列表。可以是托管式实体类型，也可以是自定义实体类型。
+  **outputColumnName** –（类型：`String`，默认值：“DetectedEntities”）用于存储检测到的实体的列名。如果未提供此参数，则默认列名为“DetectedEntities”。
+  **detectionSensitivity** –（类型：`String`，选项：“低”或“高”，默认值：“低”）指定检测过程的灵敏度。有效选项为“低”或“高”。如果未提供此参数，则默认灵敏度设置为“低”。

 `outputColumnName` 设置：

 用于存储检测到的实体的列名。如果未提供此参数，则默认列名为“DetectedEntities”。对于输出列中的每一行，补充列都用以下键值对来包含了列名与检测到的实体元数据的映射：
+  **entityType** – 检测到的实体类型。
+  **start** – 检测到的实体在原始数据中的起始位置。
+  **end** – 检测到的实体在原始数据中的结束位置。
+  **actionUsed** – 对检测到的实体执行的操作（例如，“DETECT”、“REDACT”、“PARTIAL\$1REDACT”、“SHA256\$1HASH”）。

 示例：

```
{
   "DetectedEntities":{
      "SSN Col":[
         {
            "entityType":"USA_SSN",
            "actionUsed":"DETECT",
            "start":4,
            "end":15
         }
      ],
      "Random Data col":[
         {
            "entityType":"BANK_ACCOUNT",
            "actionUsed":"PARTIAL_REDACT",
            "start":4,
            "end":13
         },
         {
            "entityType":"IP_ADDRESS",
            "actionUsed":"REDACT",
            "start":4,
            "end":13
         }
      ]
   }
}
```

 **使用精细操作的 `detect()` 方法的检测参数** 

 此方法用于使用指定的参数来检测 DynamicFrame 中的实体。此方法将返回一个新 DataFrame，其中包含遮蔽敏感数据后的原始值以及一个具有 PII 检测元数据的附加列 `outputColumnName`。

```
detect(frame: DynamicFrame, 
       detectionParameters: JsonOptions,
       outputColumnName: String = "DetectedEntities",
       detectionSensitivity: String = "LOW"): DynamicFrame
```

 参数：
+  **frame** –（类型：`DynamicFrame`）：包含要处理的数据的输入 DynamicFrame。
+  **detectionParameters** –（类型：`JsonOptions`）：为检测进程指定参数的 JSON 选项。
+  **outputColumnName** –（类型：`String`，默认值：“DetectedEntities”）：用于存储检测到的实体的列名。如果未提供此参数，则默认列名为“DetectedEntities”。
+  **detectionSensitivity** –（类型：`String`，选项：“低”或“高”，默认值：“低”）：指定检测过程的灵敏度。有效选项为“低”或“高”。如果未提供此参数，则默认灵敏度设置为“低”。

<a name="detection-parameters-settings"></a> `detectionParameters` 设置 

 如果未包含任何设置，则将使用默认值。
+  **action** –（类型：`String`，选项：“DETECT”、“REDACT”、“PARTIAL\$1REDACT”、“SHA256\$1HASH”）指定要对实体执行的操作。必需。请注意，对于执行遮蔽的操作（除“DETECT”之外的所有操作），每列只能执行一个操作。这是一种用于遮蔽合并后实体的预防措施。
+  **sourceColumns** –（类型：`List[String]`，默认值：[“\$1”]）要对实体执行检测的源列名列表。如果不存在，则默认为 [“\$1”]。如果使用的列名无效，则将引发 `IllegalArgumentException`。
+  **sourceColumnsToExclude** –（类型：`List[String]`）要对实体执行检测的源列名列表。使用 `sourceColumns` 或 `sourceColumnsToExclude`。如果使用的列名无效，则将引发 `IllegalArgumentException`。
+  **actionOptions** – 基于指定操作的附加选项：
  +  对于“DETECT”和“SHA256\$1HASH”，不允许使用任何选项。
  +  对于“REDACT”：
    + **redactText** –（键入：`String`，默认值：“\$1\$1\$1\$1\$1”）用于替换检测到的实体的文本。
  +  对于“PARTIAL\$1REDACT”：
    +  **redactChar** –（类型：`String`，默认值：“\$1”）用于替换实体中每个检测到的字符的字符。
    +  **matchPattern** –（类型：`String`）用于部分编辑的正则表达式模式。不能与 numLeftCharsToExclude 或 `numRightCharsToExclude` 组合使用。
    +  **numLeftCharsToExclude** –（类型：`String, integer`）要排除的左侧字符数。不能与 matchPattern 组合使用，但可以与 `numRightCharsToExclude` 组合使用。
    +  **numRightCharsToExclude** –（类型：`String, integer`）要排除的右侧字符数。不能与 matchPattern 组合使用，但可以与 `numRightCharsToExclude` 组合使用。

 `outputColumnName` 设置 

 [参见 outputColumnName 设置](#sensitive-data-detect-parameters-fine-grained-actions) 

## `classifyColumns()` 方法的检测参数
<a name="detection-parameters-classifycolumns"></a>

 此方法用于检测 DynamicFrame 中的实体。这将返回一个以列名为键，以检测到的实体类型列表为值的映射。返回此映射后可以在 AWS Glue 脚本中进行自定义遮蔽。

```
classifyColumns(frame: DynamicFrame, 
                entityTypesToDetect: Seq[String], 
                sampleFraction: Double = 0.1, 
                thresholdFraction: Double = 0.1,
                detectionSensitivity: String = "LOW")
```

 参数：
+  **frame** –（类型：`DynamicFrame`）包含要处理的数据的输入 DynamicFrame。
+  **entityTypesToDetect** –（类型：`Seq[String]`）要检测的实体类型列表。可以是托管式实体类型，也可以是自定义实体类型。
+  **sampleFraction** –（类型：`Double`，默认值：10%）扫描 PII 实体时的数据采样率。
+  **thresholdFraction** –（类型：`Double`，默认值：10%）：要将列标识为 PII 数据时必须达到的数据占比。
+  **detectionSensitivity** –（类型：`String`，选项：“低”或“高”，默认值：“低”）指定检测过程的灵敏度。有效选项为“低”或“高”。如果未提供此参数，则默认灵敏度设置为“低”。

# 托管敏感数据类型
<a name="sensitive-data-managed-data-types"></a>

 **全球实体** 


| 数据类型 | 类别 | 说明 | 
| --- | --- | --- | 
| PERSON\$1NAME | 通用 |  人员的姓名。  | 
| EMAIL | 个人 |  电子邮件地址。  | 
| IP\$1ADDRESS | 计算机 |  IP 地址   | 
| MAC\$1ADDRESS | 个人 |  MAC 地址。  | 



 **美国数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| BANK\$1ACCOUNT |  银行账号。但是不特定于某个国家或地区，仅检测美国和加拿大的账户格式。  | 
| CREDIT\$1CARD |  信用卡号。  | 
| PHONE\$1NUMBER |   电话号码。但是不特定于某个国家或地区，目前仅检测美国和加拿大的电话号码。  | 
| USA\$1ATIN |  美国国税局颁发的美国个人纳税识别号码。  | 
| USA\$1CPT\$1CODE |  CPT 代码（美国专用）。  | 
| USA\$1DEA\$1NUMBER |  DEA 编号（美国专用）。  | 
| USA\$1DRIVING\$1LICENSE |  驾驶执照号码（美国专用）。  | 
| USA\$1HCPCS\$1CODE |  HCPCS 代码（美国专用）。  | 
| USA\$1HEALTH\$1INSURANCE\$1CLAIM\$1NUMBER |  健康保险索赔编号（美国专用）。  | 
| USA\$1ITIN |  ITIN（适用于美国人或实体）。  | 
| USA\$1MEDICARE\$1BENEFICIARY\$1IDENTIFIER |  医疗保险受益人识别码（美国专用）。  | 
| USA\$1NATIONAL\$1DRUG\$1CODE |  NDC 代码（美国专用）。  | 
| USA\$1NATIONAL\$1PROVIDER\$1IDENTIFIER |  国家供应商识别码（美国专用）。  | 
| USA\$1PASSPORT\$1NUMBER |  护照号码（适用于美国人）。  | 
| USA\$1PTIN |  美国国税局颁发的美国报税人纳税识别号。  | 
| USA\$1SSN |  社会保障号码（适用于美国人）。  | 



 **阿根廷数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| ARGENTINA\$1TAX\$1IDENTIFICATION\$1NUMBER |   阿根廷纳税识别号。也被称为 CUIT 或 CUIL。  | 

 **澳大利亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| AUSTRALIA\$1BUSINESS\$1NUMBER |   澳大利亚商业号码（ABN）。澳大利亚商务局（ABR）颁发的唯一标识符，用于向政府和社区标识企业。  | 
| AUSTRALIA\$1COMPANY\$1NUMBER |   澳大利亚公司编号（ACN）。澳大利亚证券和投资委员会颁发的唯一标识符。  | 
| AUSTRALIA\$1DRIVING\$1LICENSE |  澳大利亚的驾驶执照号码。  | 
| AUSTRALIA\$1MEDICARE\$1NUMBER |  澳大利亚医疗保险号码。澳大利亚健康保险委员会颁发的个人身份证件。  | 
| AUSTRALIA\$1PASSPORT\$1NUMBER |  澳大利亚护照号码。  | 
| AUSTRALIA\$1TAX\$1FILE\$1NUMBER |   澳大利亚税务档案号（TFN）。由澳大利亚税务局（ATO）签发给纳税人（个人、公司等）进行税务交易。  | 

 **奥地利数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| AUSTRIA\$1DRIVING\$1LICENSE |  驾驶执照号码（奥地利专用）。  | 
| AUSTRIA\$1PASSPORT\$1NUMBER |  护照号码（奥地利专用）。  | 
| AUSTRIA\$1SSN |  社会保障号码（适用于奥地利人）。  | 
| AUSTRIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（奥地利专用）。  | 
| AUSTRIA\$1VALUE\$1ADDED\$1TAX |  增值税（奥地利专用）。  | 

 **巴尔干数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| BOSNIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  波斯尼亚―黑塞哥维亚公民的唯一主公民号码（JMBG）。  | 
| KOSOVO\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  科索沃的唯一公民主号码（JMBG）。  | 
| MACEDONIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  马其顿的唯一主公民号码。  | 
| MONTENEGRO\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  黑山的唯一公民主号码（JMBG）。  | 
| SERBIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  塞尔维亚的唯一公民主号码（JMBG）。  | 
| SERBIA\$1VALUE\$1ADDED\$1TAX |  增值税（塞尔维亚专用）。  | 
| VOJVODINA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  伏伊伏丁那的唯一公民主号码（JMBG）。  | 

 **比利时数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| BELGIUM\$1DRIVING\$1LICENSE |  驾驶执照号码（比利时专用）  | 
| BELGIUM\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  比利时国家号码（BNN）。  | 
| BELGIUM\$1PASSPORT\$1NUMBER |  护照号码（比利时专用）。  | 
| BELGIUM\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（比利时专用）。  | 
| BELGIUM\$1VALUE\$1ADDED\$1TAX |  增值税（比利时专用）。  | 

 **巴西数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| BRAZIL\$1BANK\$1ACCOUNT | 银行账号（巴西专用）。 | 
| BRAZIL\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国民识别码（巴西专用）。  | 
| BRAZIL\$1NATIONAL\$1REGISTRY\$1OF\$1LEGAL\$1ENTITIES\$1NUMBER |  颁发给公司的识别码（巴西专用），也称为 CNPJ。  | 
| BRAZIL\$1NATURAL\$1PERSON\$1REGISTRY\$1NUMBER |  自然人登记号，也称为 CPF。  | 

 **保加利亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| BULGARIA\$1DRIVING\$1LICENSE |  驾驶执照号码（保加利亚专用）。  | 
| BULGARIA\$1UNIFORM\$1CIVIL\$1NUMBER |  统一民用号码（EGN），用作国家识别码。  | 
| BULGARIA\$1VALUE\$1ADDED\$1TAX |  增值税（保加利亚专用）。  | 

 **加拿大数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| CANADA\$1DRIVING\$1LICENSE |  驾驶执照号码（加拿大专用）。  | 
| CANADA\$1GOVERNMENT\$1IDENTIFICATION\$1CARD\$1NUMBER |  国民识别码（加拿大专用）。  | 
| CANADA\$1PASSPORT\$1NUMBER |  护照号码（加拿大专用）。  | 
| CANADA\$1PERMANENT\$1RESIDENCE\$1NUMBER |  永久居留号码（PR 卡号）。  | 
| CANADA\$1PERSONAL\$1HEALTH\$1NUMBER |  医疗保健的唯一标识符（PHN 号码）。  | 
| CANADA\$1SOCIAL\$1INSURANCE\$1NUMBER |  加拿大社会保险号码（SIN）。  | 

 **智利数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| CHILE\$1DRIVING\$1LICENSE |  驾驶执照号码（智利专用）。  | 
| CHILE\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  智利国民标识符，也称为 RUT 或 RUN。  | 

 **中国、香港特别行政区、澳门特别行政区和台湾数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| CHINA\$1IDENTIFICATION |  中国标识符。  | 
| CHINA\$1LICENSE\$1PLATE\$1NUMBER |  驾驶执照号码（中国专用）。  | 
| CHINA\$1MAINLAND\$1TRAVEL\$1PERMIT\$1ID\$1HONG\$1KONG\$1MACAU |  港澳居民来往内地通行证。  | 
| CHINA\$1MAINLAND\$1TRAVEL\$1PERMIT\$1ID\$1TAIWAN |  中华人民共和国（中国）政府签发的台湾居民来往大陆通行证。  | 
| CHINA\$1PASSPORT\$1NUMBER |  护照号码（中国专用）。  | 
| CHINA\$1PHONE\$1NUMBER |  电话号码（中国专用）。  | 
| HONG\$1KONG\$1IDENTITY\$1CARD |  香港特别行政区入境事务处签发的正式身份证明文件。  | 
| MACAU\$1RESIDENT\$1IDENTITY\$1CARD |  澳门居民身份证（BIR）是由澳门特别行政区身份证明服务局签发的官方身份证。  | 
| TAIWAN\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国民识别码（台湾专用）。  | 
| TAIWAN\$1PASSPORT\$1NUMBER |  护照号码（台湾专用）。  | 

 **哥伦比亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| COLOMBIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  哥伦比亚人出生时分配的唯一标识符。  | 
| COLOMBIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（哥伦比亚专用）。  | 

 **克罗地亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| CROATIA\$1DRIVING\$1LICENSE |  驾驶执照号码（克罗地亚专用）。  | 
| CROATIA\$1IDENTITY\$1NUMBER |  国民识别码（克罗地亚专用）。  | 
| CROATIA\$1PASSPORT\$1NUMBER |  护照号码（克罗地亚专用）。  | 
| CROATIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（OIB）。  | 

 **塞浦路斯数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| CYPRUS\$1DRIVING\$1LICENSE |  驾驶执照号码（塞浦路斯专用）。  | 
| CYPRUS\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  塞浦路斯身份证。  | 
| CYPRUS\$1PASSPORT\$1NUMBER |  护照号码（塞浦路斯专用）。  | 
| CYPRUS\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（塞浦路斯专用）。  | 
| CYPRUS\$1VALUE\$1ADDED\$1TAX |  增值税（塞浦路斯专用）。  | 

 **捷克数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| CZECHIA\$1DRIVING\$1LICENSE |  驾驶执照号码（捷克专用）。  | 
| CZECHIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（捷克专用）。  | 
| CZECHIA\$1VALUE\$1ADDED\$1TAX |  增值税（捷克专用）。  | 

 **丹麦数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| DENMARK\$1DRIVING\$1LICENSE |  驾驶执照号码（丹麦专用）。  | 
| DENMARK\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（丹麦专用）。  | 
| DENMARK\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（丹麦专用）。  | 
| DENMARK\$1VALUE\$1ADDED\$1TAX |  增值税（丹麦专用）。  | 

 **爱沙尼亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| ESTONIA\$1DRIVING\$1LICENSE |  驾驶执照号码（爱沙尼亚专用）。  | 
| ESTONIA\$1PASSPORT\$1NUMBER |  护照号码（爱沙尼亚专用）。  | 
| ESTONIA\$1PERSONAL\$1IDENTIFICATION\$1CODE |  个人标识号（爱沙尼亚专用）。  | 
| ESTONIA\$1VALUE\$1ADDED\$1TAX |  增值税（爱沙尼亚专用）。  | 

 **芬兰数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| FINLAND\$1DRIVING\$1LICENSE |  驾驶执照号码（芬兰专用）。  | 
| FINLAND\$1HEALTH\$1INSURANCE\$1NUMBER |  健康保险号码（芬兰专用）。  | 
| FINLAND\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（芬兰专用）。  | 
| FINLAND\$1PASSPORT\$1NUMBER |  护照号码（芬兰专用）。  | 
| FINLAND\$1VALUE\$1ADDED\$1TAX |  增值税（芬兰专用）。  | 

 **法国数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| FRANCE\$1BANK\$1ACCOUNT |  银行账号（法国专用）。  | 
| FRANCE\$1DRIVING\$1LICENSE |  驾驶执照号码（法国专用）。  | 
| FRANCE\$1HEALTH\$1INSURANCE\$1NUMBER |  法国健康保险号码。  | 
| FRANCE\$1INSEE\$1CODE |  法国社会保障、SSN 或 NIR 号码。  | 
| FRANCE\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  法国国民识别码（CNI）。  | 
| FRANCE\$1PASSPORT\$1NUMBER |  护照号码（法国专用）。  | 
| FRANCE\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（法国专用）。  | 
| FRANCE\$1VALUE\$1ADDED\$1TAX |  增值税（法国专用）。  | 

 **德国数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| GERMANY\$1BANK\$1ACCOUNT |  银行账号（德国专用）。  | 
| GERMANY\$1DRIVING\$1LICENSE |  驾驶执照号码（德国专用）。  | 
| GERMANY\$1PASSPORT\$1NUMBER |  护照号码（德国专用）。  | 
| GERMANY\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（德国专用）。  | 
| GERMANY\$1TAX\$1IDENTIFICATION\$1NUMBER |  税务标识号（德国专用）。  | 
| GERMANY\$1VALUE\$1ADDED\$1TAX |  增值税（德国专用）。  | 

 **希腊数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| GREECE\$1DRIVING\$1LICENSE |  驾驶执照号码（希腊专用）。  | 
| GREECE\$1PASSPORT\$1NUMBER |  护照号码（希腊专用）。  | 
| GREECE\$1SSN |  社会保障号码（适用于希腊人）。  | 
| GREECE\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（希腊专用）。  | 
| GREECE\$1VALUE\$1ADDED\$1TAX |  增值税（希腊专用）。  | 

 **匈牙利数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| HUNGARY\$1DRIVING\$1LICENSE |  驾驶执照号码（匈牙利专用）。  | 
| HUNGARY\$1PASSPORT\$1NUMBER |  护照号码（匈牙利专用）。  | 
| HUNGARY\$1SSN |  社会保障号码（适用于匈牙利人）。  | 
| HUNGARY\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（匈牙利专用）。  | 
| HUNGARY\$1VALUE\$1ADDED\$1TAX |  增值税（匈牙利专用）。  | 

 **冰岛数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| ICELAND\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国民识别码（冰岛专用）。  | 
| ICELAND\$1PASSPORT\$1NUMBER |  护照号码（冰岛专用）。  | 
| ICELAND\$1VALUE\$1ADDED\$1TAX |  增值税（冰岛专用）。  | 

 **印度数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| INDIA\$1AADHAAR\$1NUMBER |  由印度唯一身份识别管理局颁发的 Aadhaar 识别号。  | 
| INDIA\$1PERMANENT\$1ACCOUNT\$1NUMBER |  印度永久编号（PAN）。  | 

 **印度尼西亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| INDONESIA\$1IDENTITY\$1CARD\$1NUMBER |  国民识别码（印度尼西亚专用）。  | 

 **爱尔兰数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| IRELAND\$1DRIVING\$1LICENSE |  驾驶执照号码（爱尔兰专用）。  | 
| IRELAND\$1PASSPORT\$1NUMBER |  护照号码（爱尔兰专用）。  | 
| IRELAND\$1PERSONAL\$1PUBLIC\$1SERVICE\$1NUMBER |  爱尔兰个人公共服务号码（PPS）。  | 
| IRELAND\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（爱尔兰专用）。  | 
| IRELAND\$1VALUE\$1ADDED\$1TAX |  增值税（爱尔兰专用）。  | 

 **以色列数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| ISRAEL\$1IDENTIFICATION\$1NUMBER |  国民识别码（以色列专用）。  | 

 **意大利数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| ITALY\$1BANK\$1ACCOUNT |  银行账号（意大利专用）。  | 
| ITALY\$1DRIVING\$1LICENSE |  驾驶执照号码（意大利专用）。  | 
| ITALY\$1FISCAL\$1CODE |  标识号，也称为意大利 Codice Fiscale。  | 
| ITALY\$1PASSPORT\$1NUMBER |  护照号码（意大利专用）。  | 
| ITALY\$1VALUE\$1ADDED\$1TAX |  增值税（意大利专用）。  | 

 **日本数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| JAPAN\$1BANK\$1ACCOUNT |  日本银行账户。  | 
| JAPAN\$1DRIVING\$1LICENSE |  日本的驾驶执照号码。  | 
| JAPAN\$1MY\$1NUMBER |  日本公民或公司的唯一识别码，用于税务管理、社会保障管理和灾难响应   | 
| JAPAN\$1PASSPORT\$1NUMBER |  日本护照号码。  | 

 **韩国数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| KOREA\$1PASSPORT\$1NUMBER |  护照号码（韩国专用）。  | 
| KOREA\$1RESIDENCE\$1REGISTRATION\$1NUMBER\$1FOR\$1CITIZENS |  韩国居民身份证号码。  | 
| KOREA\$1RESIDENCE\$1REGISTRATION\$1NUMBER\$1FOR\$1FOREIGNERS |  外国人韩国居留登记号码。  | 

 **拉脱维亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| LATVIA\$1DRIVING\$1LICENSE |  驾驶执照号码（拉脱维亚专用）。  | 
| LATVIA\$1PASSPORT\$1NUMBER |  护照号码（拉脱维亚专用）。  | 
| LATVIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（拉脱维亚专用）。  | 
| LATVIA\$1VALUE\$1ADDED\$1TAX |  增值税（拉脱维亚专用）。  | 

 **列支敦士登数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| LIECHTENSTEIN\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国民识别码（列支敦士登专用）。  | 
| LIECHTENSTEIN\$1PASSPORT\$1NUMBER |  护照号码（列支敦士登专用）。  | 
| LIECHTENSTEIN\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（列支敦士登专用）。  | 

 **立陶宛数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| LITHUANIA\$1DRIVING\$1LICENSE |  驾驶执照号码（立陶宛专用）。  | 
| LITHUANIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（立陶宛专用）。  | 
| LITHUANIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（立陶宛专用）。  | 
| LITHUANIA\$1VALUE\$1ADDED\$1TAX |  增值税（立陶宛专用）。  | 

 **卢森堡数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| LUXEMBOURG\$1DRIVING\$1LICENSE |  驾驶执照号码（卢森堡专用）。  | 
| LUXEMBOURG\$1NATIONAL\$1INDIVIDUAL\$1NUMBER |  国民识别码（卢森堡专用）。  | 
| LUXEMBOURG\$1PASSPORT\$1NUMBER |  护照号码（卢森堡专用）。  | 
| LUXEMBOURG\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（卢森堡专用）。  | 
| LUXEMBOURG\$1VALUE\$1ADDED\$1TAX |  增值税（卢森堡专用）。  | 

 **马来西亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| MALAYSIA\$1MYKAD\$1NUMBER |  国民识别码（马来西亚专用）。  | 
| MALAYSIA\$1PASSPORT\$1NUMBER |  护照号码（马来西亚专用）。  | 

 **马耳他数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| MALTA\$1DRIVING\$1LICENSE |  驾驶执照号码（马耳他专用）。  | 
| MALTA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国民识别码（马耳他专用）。  | 
| MALTA\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（马耳他专用）。  | 
| MALTA\$1VALUE\$1ADDED\$1TAX |  增值税（马耳他专用）。  | 

 **墨西哥数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| MEXICO\$1CLABE\$1NUMBER |  墨西哥 CLABE（Clave Bancaria Estandarizada）银行账号。  | 
| MEXICO\$1DRIVING\$1LICENSE |  驾驶执照号码（墨西哥专用）。  | 
| MEXICO\$1PASSPORT\$1NUMBER |  护照号码（墨西哥专用）。  | 
| MEXICO\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（墨西哥专用）。  | 
| MEXICO\$1UNIQUE\$1POPULATION\$1REGISTRY\$1CODE |  Clave Única de Registro de Población（CURP）墨西哥唯一标识码。  | 

 **荷兰数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| NETHERLANDS\$1CITIZEN\$1SERVICE\$1NUMBER |  荷兰公民号码（BSN，burgerserviceNummer）。  | 
| NETHERLANDS\$1DRIVING\$1LICENSE |  驾驶执照号码（荷兰专用）。  | 
| NETHERLANDS\$1PASSPORT\$1NUMBER |  护照号码（荷兰专用）。  | 
| NETHERLANDS\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（荷兰专用）。  | 
| NETHERLANDS\$1VALUE\$1ADDED\$1TAX |  增值税（荷兰专用）。  | 
| NETHERLANDS\$1BANK\$1ACCOUNT |  银行账号（荷兰专用）。  | 

 **新西兰数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| NEW\$1ZEALAND\$1DRIVING\$1LICENSE |  驾驶执照号码（新西兰专用）。  | 
| NEW\$1ZEALAND\$1NATIONAL\$1HEALTH\$1INDEX\$1NUMBER |  新西兰国民健康指数编号。  | 
| NEW\$1ZEALAND\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号，也称为内陆税务号码（新西兰专用）。  | 

 **挪威数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| NORWAY\$1BIRTH\$1NUMBER |  挪威国民身份证号码。  | 
| NORWAY\$1DRIVING\$1LICENSE |  驾驶执照号码（挪威专用）。  | 
| NORWAY\$1HEALTH\$1INSURANCE\$1NUMBER |  挪威健康保险号码。  | 
| NORWAY\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（挪威专用）。  | 
| NORWAY\$1VALUE\$1ADDED\$1TAX |  增值税（挪威专用）。  | 

 **菲律宾数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| PHILIPPINES\$1DRIVING\$1LICENSE |  驾驶执照号码（菲律宾专用）。  | 
| PHILIPPINES\$1PASSPORT\$1NUMBER |  护照号码（菲律宾专用）。  | 

 **波兰数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| POLAND\$1DRIVING\$1LICENSE |  驾驶执照号码（波兰专用）。  | 
| POLAND\$1IDENTIFICATION\$1NUMBER |  波兰标识符。  | 
| POLAND\$1PASSPORT\$1NUMBER |  护照号码（波兰专用）。  | 
| POLAND\$1REGON\$1NUMBER |  REGON 标识号，也称为统计标识号。  | 
| POLAND\$1SSN |  社会保障号码（适用于波兰人）。  | 
| POLAND\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（波兰专用）。  | 
| POLAND\$1VALUE\$1ADDED\$1TAX |  增值税（波兰专用）。  | 

 **葡萄牙数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| PORTUGAL\$1DRIVING\$1LICENSE |  驾驶执照号码（葡萄牙专用）。  | 
| PORTUGAL\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（葡萄牙专用）。  | 
| PORTUGAL\$1PASSPORT\$1NUMBER |  护照号码（葡萄牙专用）。  | 
| PORTUGAL\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（葡萄牙专用）。  | 
| PORTUGAL\$1VALUE\$1ADDED\$1TAX |  增值税（葡萄牙专用）。  | 

 **罗马尼亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| ROMANIA\$1DRIVING\$1LICENSE |  驾驶执照号码（罗马尼亚专用）。  | 
| ROMANIA\$1NUMERICAL\$1PERSONAL\$1CODE |  个人标识号（罗马尼亚专用）。  | 
| ROMANIA\$1PASSPORT\$1NUMBER |  护照号码（罗马尼亚专用）。  | 
| ROMANIA\$1VALUE\$1ADDED\$1TAX |  增值税（罗马尼亚专用）。  | 

 **新加坡数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SINGAPORE\$1DRIVING\$1LICENSE |  驾驶执照号码（新加坡专用）。  | 
| SINGAPORE\$1NATIONAL\$1REGISTRY\$1IDENTIFICATION\$1NUMBER |  新加坡国家注册标识卡。  | 
| SINGAPORE\$1PASSPORT\$1NUMBER |  护照号码（新加坡专用）。  | 
| SINGAPORE\$1UNIQUE\$1ENTITY\$1NUMBER |  新加坡唯一实体编号。  | 

 **斯洛伐克数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SLOVAKIA\$1DRIVING\$1LICENSE |  驾驶执照号码（斯洛伐克专用）。  | 
| SLOVAKIA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（斯洛伐克专用）。  | 
| SLOVAKIA\$1PASSPORT\$1NUMBER |  护照号码（斯洛伐克专用）。  | 
| SLOVAKIA\$1VALUE\$1ADDED\$1TAX |  增值税（斯洛伐克专用）。  | 

 **斯洛文尼亚数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SLOVENIA\$1DRIVING\$1LICENSE |  驾驶执照号码（斯洛文尼亚专用）。  | 
| SLOVENIA\$1PASSPORT\$1NUMBER |  护照号码（斯洛文尼亚专用）。  | 
| SLOVENIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  纳税识别号（斯洛文尼亚专用）。  | 
| SLOVENIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  斯洛文尼亚公民的唯一主公民号码（JMBG）。  | 
| SLOVENIA\$1VALUE\$1ADDED\$1TAX |  增值税（斯洛文尼亚专用）。  | 

 **南非数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SOUTH\$1AFRICA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（南非专用）。  | 

 **西班牙数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SPAIN\$1BANK\$1ACCOUNT |  银行账号（西班牙专用）。  | 
| SPAIN\$1DNI |  西班牙国民身份证（Documento Nacional de Identidad）。  | 
| SPAIN\$1DRIVING\$1LICENSE |  驾驶执照号码（西班牙专用）。  | 
| SPAIN\$1NIE |  外国人身份号码（西班牙专用），也称为 NIE。  | 
| SPAIN\$1NIF |  纳税识别号（西班牙专用），也称为 NIF。  | 
| SPAIN\$1PASSPORT\$1NUMBER |  护照号码（西班牙专用）。  | 
| SPAIN\$1SSN |  社会保障号码（适用于西班牙人）。  | 
| SPAIN\$1VALUE\$1ADDED\$1TAX |  增值税（西班牙专用）。  | 

 **斯里兰卡数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SRI\$1LANKA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国民识别码（斯里兰卡专用）。  | 

 **瑞典数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SWEDEN\$1DRIVING\$1LICENSE |  驾驶执照号码（瑞典专用）。  | 
| SWEDEN\$1PASSPORT\$1NUMBER |  护照号码（瑞典专用）。  | 
| SWEDEN\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（瑞典专用）。  | 
| SWEDEN\$1TAX\$1IDENTIFICATION\$1NUMBER |  瑞典纳税识别号（人员编号）。  | 
| SWEDEN\$1VALUE\$1ADDED\$1TAX |  增值税（瑞典专用）。  | 

 **瑞士数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| SWITZERLAND\$1AHV |  瑞士人的社会保障号码（AHV）。  | 
| SWITZERLAND\$1HEALTH\$1INSURANCE\$1NUMBER |  瑞士健康保险号码。  | 
| SWITZERLAND\$1PASSPORT\$1NUMBER |  护照号码（瑞士专用）。  | 
| SWITZERLAND\$1VALUE\$1ADDED\$1TAX |  增值税（瑞士专用）。  | 

 **泰国数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| THAILAND\$1PASSPORT\$1NUMBER |  护照号码（泰国专用）。  | 
| THAILAND\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  个人标识号（泰国专用）。  | 

 **土耳其数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| TURKEY\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（土耳其专用）。  | 
| TURKEY\$1PASSPORT\$1NUMBER |  护照号码（土耳其专用）。  | 
| TURKEY\$1VALUE\$1ADDED\$1TAX |  增值税（土耳其专用）。  | 

 **乌克兰数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| UKRAINE\$1INDIVIDUAL\$1IDENTIFICATION\$1NUMBER |  唯一标识符（乌克兰专用）。  | 
| UKRAINE\$1PASSPORT\$1NUMBER\$1DOMESTIC |  国内护照号码（乌克兰专用）。  | 
| UKRAINE\$1PASSPORT\$1NUMBER\$1INTERNATIONAL |  国际护照号码（乌克兰专用）。  | 

 **阿拉伯联合酋长国（UAE）数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| UNITED\$1ARAB\$1EMIRATES\$1PERSONAL\$1NUMBER |  个人标识号（UAE 专用）。  | 

 **英国数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| UK\$1BANK\$1ACCOUNT |  英国（UK）银行账户。  | 
| UK\$1BANK\$1SORT\$1CODE |   英国（UK）银行分类代码。银行识别代码是用于通过各自的清算组织在各自国家或地区的银行之间进行汇款的银行代码   | 
| UK\$1DRIVING\$1LICENSE |  大不列颠及北爱尔兰联合王国的驾照号码（英国专用）  | 
| UK\$1ELECTORAL\$1ROLL\$1NUMBER |  选民名册编号 (ERN) 是发给个人进行英国选举登记的识别号。该号码的格式由英国内阁办公室的《英国政府标准》规定  | 
| UK\$1NATIONAL\$1HEALTH\$1SERVICE\$1NUMBER |  国家健康服务（NHS）号码是分配给英国公共卫生服务注册用户的唯一号码  | 
| UK\$1NATIONAL\$1INSURANCE\$1NUMBER |  国民保险号码 (NINO) 是英国 (UK) 用于针对国民保险计划或社会保障体系识别个人的号码。该号码有时被称为 NI No 或 NINO。  | 
| UK\$1PASSPORT\$1NUMBER |  英国（UK）护照号码。  | 
| UK\$1UNIQUE\$1TAXPAYER\$1REFERENCE\$1NUMBER |  英国 (UK) 唯一纳税人参考号 (UTR)。英国政府用来管理税收系统的识别码   | 
| UK\$1VALUE\$1ADDED\$1TAX |  增值税是由最终消费者承担的消费税。制造和分销过程中的每笔交易都要支付增值税。对于英国，增值税编号由企业所在地区的增值税办公室发布  | 
| UK\$1PHONE\$1NUMBER |  英国（UK）电话号码。  | 

 **委内瑞拉数据类型** 


| 数据类型 | 说明 | 
| --- | --- | 
| VENEZUELA\$1DRIVING\$1LICENSE |  驾驶执照号码（委内瑞拉专用）。  | 
| VENEZUELA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  国家标识号（委内瑞拉专用）。  | 
| VENEZUELA\$1VALUE\$1ADDED\$1TAX |  增值税（委内瑞拉专用）。  | 

# 使用精细敏感数据检测
<a name="sensitive-data-fine-grained-actions"></a>

**注意**  
 精细操作功能仅在 AWS Glue 3.0 和 4.0 中可用。这包括 AWS Glue Studio 体验。此外，2.0 版本也不支持持久审计日志更改。  
 所有 AWS Glue Studio 3.0 和 4.0 可视化作业都将创建一个会自动使用精细操作 API 的脚本。

 借助检测敏感数据转换功能，可以检测、遮蔽或移除您定义的或由 AWS Glue 预定义的实体。您还可以借助精细操作对每个实体应用特定的操作。其他优点包括：
+  可在检测到数据后立即应用操作，从而提高性能。
+  提供了包含或排除特定列的选项。
+  能够使用部分遮蔽功能。从而让您可以部分遮蔽检测到的敏感数据实体，而不是遮蔽整个字符串。支持带有偏移量的简单参数和正则表达式。

 以下是敏感数据检测 API 代码片段和下一节中引用的示例作业中使用的精细操作。

 **检测 API** – 精细操作将使用新的 `detectionParameters` 参数：

```
def detect(
    frame: DynamicFrame,
    detectionParameters: JsonOptions,
    outputColumnName: String = "DetectedEntities",
    detectionSensitivity: String = "LOW"
): DynamicFrame = {}
```

## 将敏感数据检测 API 与精细操作结合使用
<a name="sensitive-data-fine-grained-actions-glue-jobs"></a>

 敏感数据检测 API 使用 **detect** 来分析给定的数据，确定行或列是否属于敏感数据实体类型，并且将运行用户为每种实体类型指定的操作。

### 将 detect API 与精细操作结合使用
<a name="sensitive-data-fine-grained-actions-glue-jobs-detect"></a>

 使用 **detect** API 并指定 `outputColumnName` 和 ` detectionParameters`。

```
    object GlueApp {
      def main(sysArgs: Array[String]) {
      
        val spark: SparkContext = new SparkContext()
        val glueContext: GlueContext = new GlueContext(spark)
        
        // @params: [JOB_NAME]
        val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
        Job.init(args("JOB_NAME"), glueContext, args.asJava)
        
        // Script generated for node S3 bucket. Creates DataFrame from data stored in S3.
        val S3bucket_node1 = glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ",", "optimizePerformance": false}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://189657479688-ddevansh-pii-test-bucket/tiny_pii.csv"], "recurse": true}"""), transformationContext="S3bucket_node1").getDynamicFrame()
     
        // Script generated for node Detect Sensitive Data. Will run detect API for the DataFrame
        // detectionParameter contains information on which EntityType are being detected
        // and what actions are being applied to them when detected. 
        val DetectSensitiveData_node2 = EntityDetector.detect(
            frame = S3bucket_node1, 
            detectionParameters = JsonOptions(
             """
                {
                    "PHONE_NUMBER": [
                        {
                            "action": "PARTIAL_REDACT",
                            "actionOptions": {
                                "numLeftCharsToExclude": "3",
                                "numRightCharsToExclude": "4",
                                "redactChar": "#"
                            },
                            "sourceColumnsToExclude": [ "Passport No", "DL NO#" ]
                        }
                    ],
                    "USA_PASSPORT_NUMBER": [
                        {
                            "action": "SHA256_HASH",
                            "sourceColumns": [ "Passport No" ]
                        }
                    ],
                    "USA_DRIVING_LICENSE": [
                        {
                            "action": "REDACT",
                            "actionOptions": {
                                "redactText": "USA_DL"
                            },
                            "sourceColumns": [ "DL NO#" ]
                        }
                    ]
                    
                }
            """
            ),
            outputColumnName = "DetectedEntities"
        )
     
        // Script generated for node S3 bucket. Store Results of detect to S3 location
        val S3bucket_node3 = glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://amzn-s3-demo-bucket/test-output/", "partitionKeys": []}"""), transformationContext="S3bucket_node3", format="json").writeDynamicFrame(DetectSensitiveData_node2)
     
        Job.commit()
      }
```

 上面的脚本将从 Amazon S3 中的某个位置创建一个 DataFrame，然后运行 `detect` API。由于 `detect` API 要求字段 `detectionParameters`（实体名称与将用于该实体的所有操作设置列表的映射）由 AWS Glue 的 `JsonOptions` 对象来表示，因此还有利于我们扩展该 API 的功能。

 对于为每个实体指定的每个操作，输入要应用该实体/操作组合的所有列名的列表。这让您能够为数据集中的每一列自定义要检测的实体，并跳过您知道特定列中并未包含的实体。此外，这还让您能够不对这些实体执行不必要的检测调用，从而提高作业性能，并且能够为每个列和实体组合所特有的操作。

 如果更深入看 `detectionParameters`，示例作业中有三种实体类型，分别是 `Phone Number`、`USA_PASSPORT_NUMBER` 和 `USA_DRIVING_LICENSE`。AWS Glue 将针对每种实体类型运行不同的操作，分别是 `PARTIAL_REDACT`、`SHA256_HASH`、`REDACT` 和 `DETECT`。每种实体类型也必须拥有要应用到的 `sourceColumns` 和/或 `sourceColumnsToExclude`（如果检测到）。

**注意**  
 每列只能使用一个就地编辑操作（`PARTIAL_REDACT`、`SHA256_HASH` 或 `REDACT`），但 `DETECT` 操作可以与这些操作中的任何一个结合使用。

 `detectionParameters` 字段的布局如下：

```
    ENTITY_NAME -> List[Actions]
    {
    	"ENTITY_NAME": [{
    		Action, // required
    		ColumnSpecs,
    		ActionOptionsMap
        }],
        "ENTITY_NAME2": [{
    		...
        }]
    }
```

 `actions` 和 `actionOptions` 的类型列举如下：

```
DETECT
{
    # Required
    "action": "DETECT",
    # Optional, depending on action chosen
    "actionOptions": {
        // There are no actionOptions for DETECT 
    },
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}

SHA256_HASH
{
    # Required
    "action": "SHA256_HASH",
    # Required or optional, depending on action chosen
    "actionOptions": {
        // There are no actionOptions for SHA256_HASH
    },
    
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}

REDACT
{
    # Required
    "action": "REDACT",
    # Required or optional, depending on action chosen
    "actionOptions": {
        // The text that is being replaced
        "redactText": "USA_DL"
    },
    
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}

PARTIAL_REDACT
{
    # Required
    "action": "PARTIAL_REDACT",
    # Required or optional, depending on action chosen
    "actionOptions": {
        // number of characters to not redact from the left side 
        "numLeftCharsToExclude": "3",
        // number of characters to not redact from the right side
        "numRightCharsToExclude": "4",
        // the partial redact will be made with this redacted character  
        "redactChar": "#",
        // regex pattern for partial redaction
        "matchPattern": "[0-9]"
    },
    
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}
```

 脚本运行后，结果将输出到给定的 Amazon S3 位置。您可以在 Amazon S3 中查看数据，但对于选定的实体类型，将根据所选操作进行敏感化处理。在此例中，结果行将如下所示：

```
{
    "Name": "Colby Schuster",
    "Address": "39041 Antonietta Vista, South Rodgerside, Nebraska 24151",
    "Car Owned": "Fiat",
    "Email": "Kitty46@gmail.com",
    "Company": "O'Reilly Group",
    "Job Title": "Dynamic Functionality Facilitator",
    "ITIN": "991-22-2906",
    "Username": "Cassandre.Kub43",
    "SSN": "914-22-2906",
    "DOB": "2020-08-27",
    "Phone Number": "1-2#######1718",
    "Bank Account No": "69741187",
    "Credit Card Number": "6441-6289-6867-2162-2711",
    "Passport No": "94f311e93a623c72ccb6fc46cf5f5b0265ccb42c517498a0f27fd4c43b47111e",
    "DL NO#": "USA_DL"
}
```

 上面的脚本对 `Phone Number` 使用 `#` 进行了部分编辑。`Passport No` 已更改为 SHA256 哈希值。检测到 `DL NO# ` 属于美国驾驶执照号码，并如 `detectionParameters` 中所述编辑为“USA\$1DL”。

**注意**  
 由于 classifyColumns API 的性质，无法与精细操作结合使用。此 API 会执行列采样（可由用户调整，不过有默认值）来提高检测速度。由于这一原因，精细操作将需要迭代每个值。

### 持久审计日志
<a name="sensitive-data-fine-grained-actions-persistent-audit-log"></a>

 随精细操作引入的一项新功能（但在使用普通 API 时也可用）是持久审计日志。目前，运行 detect API 会添加一个带有 PII 检测元数据的附加列（默认为 `DetectedEntities`，但可通过 `outputColumnName` 进行自定义）参数。现在推出了“actionUsed”元数据键，可以是 `DETECT`、`PARTIAL_REDACT`、`SHA256_HASH` 或 `REDACT`。

```
"DetectedEntities": {
    "Credit Card Number": [
        {
            "entityType": "CREDIT_CARD",
            "actionUsed": "DETECT",
            "start": 0,
            "end": 19
        }
    ],
    "Phone Number": [
        {
            "entityType": "PHONE_NUMBER",
            "actionUsed": "REDACT",
            "start": 0,
            "end": 14
        }
    ]
}
```

 即使客户使用不支持精细操作（例如 `detect(entityTypesToDetect, outputColumnName)`）的 API，也会在生成的数据帧中看到此持久审计日志。

 如果客户使用支持精细操作的 API，则将看到所有操作，无论是否经过编辑。示例：

```
+---------------------+----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Credit Card Number  |  Phone Number  |                                                                                            DetectedEntities                                                                                             |
+---------------------+----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 622126741306XXXX    | +12#####7890   | {"Credit Card Number":[{"entityType":"CREDIT_CARD","actionUsed":"PARTIAL_REDACT","start":0,"end":16}],"Phone Number":[{"entityType":"PHONE_NUMBER","actionUsed":"PARTIAL_REDACT","start":0,"end":12}]}} |
| 6221 2674 1306 XXXX | +12#######7890 | {"Credit Card Number":[{"entityType":"CREDIT_CARD","actionUsed":"PARTIAL_REDACT","start":0,"end":19}],"Phone Number":[{"entityType":"PHONE_NUMBER","actionUsed":"PARTIAL_REDACT","start":0,"end":14}]}} |
| 6221-2674-1306-XXXX | 22#######7890  | {"Credit Card Number":[{"entityType":"CREDIT_CARD","actionUsed":"PARTIAL_REDACT","start":0,"end":19}],"Phone Number":[{"entityType":"PHONE_NUMBER","actionUsed":"PARTIAL_REDACT","start":0,"end":14}]}} |
+---------------------+----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

 如果您不想看到 **DetectedEntities** 列，则只需在自定义脚本中删除该附加列即可。

# AWS Glue 可视化任务 API
<a name="visual-job-api-chapter"></a>

 AWS Glue 提供了一个 API，允许客户使用 AWS Glue API 从表示可视化步骤工作流的 JSON 对象创建数据集成任务。然后，客户可以使用 AWS Glue Studio 中的可视化编辑器来处理这些任务。

 有关可视化任务 API 数据类型的更多信息，请参阅[可视化任务 API](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-visual-job-api.html)。

**Topics**
+ [

## API 设计和 CRUD API
](#visual-job-api-design)
+ [

## 开始使用
](#getting-started-visual-job-api)
+ [

## 可视化任务限制
](#visual-job-limitations)

## API 设计和 CRUD API
<a name="visual-job-api-design"></a>

 CreateJob 和 UpdateJob [API](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html) 现在支持额外的可选参数 codeGenConfigurationNodes。若为此字段提供非空 JSON 结构，将导致为创建的任务在 AWS Glue Studio 中注册 DAG，并生成关联代码。任务创建时此字段的空值或空字符串将被忽略。

 codeGenConfigurationNodes 字段的更新可通过 UpdateJob AWS Glue API 以类似于 CreateJob 的方式完成。整个字段应在 UpdateJob 中指定，其中 DAG 已根据需要更改。提供的空值将被忽略，并且不会执行 DAG 更新。空结构或字符串将导致 codeGenConfigurationNodes 设置为空，并删除以前的任何 DAG。GetJob API 将返回 DAG（如果存在）。DeleteJob API 还会删除任何关联的 DAG。

## 开始使用
<a name="getting-started-visual-job-api"></a>

 要创建任务，请使用 [ CreateJob 操作](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-CreateJob)。`CreateJob` 请求输入包含一个额外的字段“codeGenConfigurationNodes”，您可以从中获取并指定 JSON 中的 DAG 对象。

 请记住以下事项：
+  “codeGenConfigurationNodes”字段是 nodeId 到节点的映射。
+  每个节点都以一个标识其节点类型的键开头。
+  由于节点只能是一种类型，因此只能指定一个键。
+  输入字段包含当前节点的父节点。

 以下是 **CreateJob** 输入的 JSON 表示。

```
{
  "node-1": {
    "S3CatalogSource": {
      "Table": "csvFormattedTable",
      "PartitionPredicate": "",
      "Name": "S3 bucket",
      "AdditionalOptions": {},
      "Database": "myDatabase"
    }
  },
  "node-3": {
    "S3DirectTarget": {
      "Inputs": ["node-2"],
      "PartitionKeys": [],
      "Compression": "none",
      "Format": "json",
      "SchemaChangePolicy": { "EnableUpdateCatalog": false },
      "Path": "",
      "Name": "S3 bucket"
    }
  },
  "node-2": {
    "ApplyMapping": {
      "Inputs": ["node-1"],
      "Name": "ApplyMapping",
      "Mapping": [
        {
          "FromType": "long",
          "ToType": "long",
          "Dropped": false,
          "ToKey": "myheader1",
          "FromPath": ["myheader1"]
        },
        {
          "FromType": "long",
          "ToType": "long",
          "Dropped": false,
          "ToKey": "myheader2",
          "FromPath": ["myheader2"]
        },
        {
          "FromType": "long",
          "ToType": "long",
          "Dropped": false,
          "ToKey": "myheader3",
          "FromPath": ["myheader3"]
        }
      ]
    }
  }
}
```

 **更新和获取任务** 

 由于 *UpdateJob* 也包含“codeGenConfigurationNodes”字段，因此输入格式相同。请参阅 [UpdateJob](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-UpdateJob) 操作。

 *GetJob* 操作也将以相同的格式返回“codeGenConfigurationNodes”字段。请参阅 [GetJob](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-GetJob) 操作。

## 可视化任务限制
<a name="visual-job-limitations"></a>

 由于“codeGenConfigurationNodes”参数已添加到现有 API 中，因此将继承这些 API 中的任何限制。此外，codeGenConfigurationNodes 和某些节点的大小也将受到限制。有关更多信息，请参阅[任务结构](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-Job)。