

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 搭配 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)
+ [在 Glue 中使用 Hudi AWS 架構](aws-glue-programming-etl-format-hudi.md)
+ [在 Glue AWS 中使用 Delta Lake 架構](aws-glue-programming-etl-format-delta-lake.md)
+ [在 Glue AWS 中使用 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 方法不支援讀取和寫入資料湖架構資料表。改用適用於 DataFrame 或 Spark DataFrame API 的 `GlueContext` 方法。
  + `create_dynamic_frame.from_catalog`
  + `write_dynamic_frame.from_catalog`
  + `getDynamicFrame`
  + `writeDynamicFrame`
+ 下列適用於 DataFrame 的 `GlueContext` 方法支援 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 不支援 Hudi 讀取時合併 (MoR) 資料表。
+ `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)

**注意**  
只有 4.0 AWS Glue 版支援透過 Lake Formation 整合 AWS Glue ETL 的 Apache Hudi、Apache Iceberg 和 Delta Lake 許可。

Apache Iceberg 透過 Lake Formation 許可與 AWS Glue ETL 提供最佳整合。其支援幾乎所有操作 (包含 SQL 支援)。

Hudi 支援大多數基本操作 (除管理操作外)。這是因為這些選項通常會透過 DataFrame 寫入完成，並透過 `additional_options` 指定。您需要使用 AWS Glue APIs為您的操作建立 DataFrames，因為 SparkSQL 不受支援。

Delta Lake 僅支援讀取、附加及覆寫資料表資料。Delta Lake 需要使用自有的程式庫才可執行不同任務 (例如，更新)。

下列功能不適用於 Lake Formation 權限管理的 Iceberg 資料表。
+ 使用 AWS Glue ETL 壓縮
+ 透過 AWS Glue ETL 的 Spark SQL 支援

下列為 Lake Formation 權限管理的 Hudi 資料表限制：
+ 移除遺棄的檔案

下列為 Lake Formation 權限管理的 Delta Lake 資料表限制：
+ 插入 Delta Lake 資料表和從其中讀取以外的所有功能。

# 在 Glue 中使用 Hudi AWS 架構
<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 資料表上執行讀取和寫入操作，或使用 Glue Data Catalog 使用 Hudi AWS 資料表。還支援其他操作，包括插入、更新和所有 [Apache Spark 操作](https://hudi.apache.org/docs/quick-start-guide/)。

**注意**  
Glue 5.0 中的 Apache Hudi AWS 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 不支援 Hudi 讀取時合併 (MoR) 資料表。

下表列出每個 Glue 版本中包含的 Hudi AWS 版本。


****  

| 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>

若要啟用 Hudi for AWS Glue，請完成下列任務：
+ 指定 `hudi` 作為 `--datalake-formats` 任務參數的值。如需詳細資訊，請參閱[在 Glue AWS 任務中使用任務參數](aws-glue-programming-etl-glue-arguments.md)。
+ 為您的 Glue 任務建立名為 AWS `--conf`的金鑰，並將其設定為下列值。您也可以選擇在指令碼中使用 `SparkConf` 設定以下組態。這些設定有助於 Apache Spark 正確處理 Hudi 資料表。

  ```
  spark.serializer=org.apache.spark.serializer.KryoSerializer
  ```
+ Glue 4.0 預設會啟用 Hudi AWS 的 Lake Formation 許可支援。讀取/寫入 Lake Formation 註冊的 Hudi 資料表時，不需要其他組態。若要讀取已註冊的 Hudi 資料表，Glue AWS 任務 IAM 角色必須具有 SELECT 許可。若要寫入已註冊的 Hudi 資料表，Glue AWS 任務 IAM 角色必須具有 SUPER 許可。若要進一步了解管理 Lake Formation 權限的資訊，請參閱[授予和撤銷 Data Catalog 資源的權限](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 Data Catalog 中註冊
<a name="aws-glue-programming-etl-format-hudi-write"></a>

此範例指令碼示範如何將 Hudi 資料表寫入 Amazon S3，並將資料表註冊至 AWS Glue Data Catalog。此範例使用 Hudi [Hive 同步工具](https://hudi.apache.org/docs/syncing_metastore/)來註冊該資料表。

**注意**  
此範例需要您設定`--enable-glue-datacatalog`任務參數，才能使用 AWS Glue Data Catalog 做為 Apache Spark Hive 中繼存放區。如需詳細資訊，請參閱 [在 Glue AWS 任務中使用任務參數](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()
```

------

## 範例：使用 Glue Data Catalog 從 Amazon S3 AWS 讀取 Hudi 資料表
<a name="aws-glue-programming-etl-format-hudi-read"></a>

此範例會讀取您從 Amazon S3 在 [範例：將 Hudi 資料表寫入 Amazon S3，並在 AWS Glue Data Catalog 中註冊](#aws-glue-programming-etl-format-hudi-write) 中建立的 Hudi 資料表。

**注意**  
此範例需要您設定`--enable-glue-datacatalog`任務參數，才能使用 AWS Glue Data Catalog 做為 Apache Spark Hive 中繼存放區。如需詳細資訊，請參閱 [在 Glue AWS 任務中使用任務參數](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()
  }
}
```

------

## 範例：在 Amazon S3 中更新 `DataFrame` 並將其插入到 Hudi 資料表中
<a name="aws-glue-programming-etl-format-hudi-update-insert"></a>

此範例使用 AWS Glue Data Catalog 將 DataFrame 插入您在 中建立的 Hudi 資料表[範例：將 Hudi 資料表寫入 Amazon S3，並在 AWS Glue Data Catalog 中註冊](#aws-glue-programming-etl-format-hudi-write)。

**注意**  
此範例需要您設定`--enable-glue-datacatalog`任務參數，才能使用 AWS Glue Data Catalog 做為 Apache Spark Hive 中繼存放區。如需詳細資訊，請參閱 [在 Glue AWS 任務中使用任務參數](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 將 Hudi 資料表寫入 Amazon S3
<a name="aws-glue-programming-etl-format-hudi-write-spark"></a>

此範例使用 Spark 將 Hudi 資料表寫入 Amazon S3。

------
#### [ 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 權限控制，您將需要先在 Lake Formation 中註冊資料表 Amazon S3 路徑。如需詳細資訊，請參閱 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html) (註冊 Amazon S3 位置)。您可以從 Lake Formation 主控台或使用 CLI AWS 註冊：

      ```
      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. 將 Lake Formation 許可授予 AWS Glue 任務 IAM 角色。您可以從 Lake Formation 主控台授予許可，或使用 AWS CLI。如需詳細資訊，請參閱[使用 Lake Formation 主控台和具名資源方法授予資料表權限](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html)。

1.  讀取在 Lake Formation 中註冊的 Hudi 資料表。該程式碼與讀取未註冊之 Hudi 資料表的程式碼相同。請注意，Glue AWS 任務 IAM 角色需要具有 SELECT 許可才能成功讀取。

   ```
    val dataFrame = glueContext.getCatalogSource(
         database = "<your_database_name>",
         tableName = "<your_table_name>"
       ).getDataFrame()
   ```

1. 寫入在 Lake Formation 中註冊的 Hudi 資料表。該程式碼與寫入未註冊之 Hudi 資料表的程式碼相同。請注意，Glue AWS 任務 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)
   ```

# 在 Glue AWS 中使用 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 資料表上執行讀取和寫入操作，或使用 Glue Data Catalog 使用 Delta Lake AWS 資料表。插入、更新和[資料表批次讀取和寫入](https://docs.delta.io/0.7.0/api/python/index.html)等操作也受到支援。使用 Delta Lake 資料表時，您還可以選擇使用 Delta Lake Python 程式庫中的方法，例如 `DeltaTable.forPath`。如需有關 Delta Lake Python 程式庫的詳細資訊，請參閱 Delta Lake 的 Python 文件。

下表列出每個 Glue 版本中包含的 Delta Lake AWS 版本。


****  

| AWS Glue 版本 | 支援的 Delta Lake 版本 | 
| --- | --- | 
| 5.1 | 3.3.2 | 
| 5.0 | 3.3.0 | 
| 4.0 | 2.1.0 | 
| 3.0 | 1.0.0 | 

若要進一步了解 Glue AWS 支援的資料湖架構，請參閱 [搭配 AWS Glue ETL 任務使用資料湖架構](aws-glue-programming-etl-datalake-native-frameworks.md)。

## 啟用 Delta Lake for AWS Glue
<a name="aws-glue-programming-etl-format-delta-lake-enable"></a>

若要啟用 Delta Lake for AWS Glue，請完成下列任務：
+ 指定 `delta` 作為 `--datalake-formats` 任務參數的值。如需詳細資訊，請參閱[在 Glue AWS 任務中使用任務參數](aws-glue-programming-etl-glue-arguments.md)。
+ 為您的 Glue 任務建立名為 AWS `--conf`的金鑰，並將其設定為下列值。您也可以選擇在指令碼中使用 `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
  ```
+ Glue 4.0 預設會啟用 Delta 資料表的 Lake Formation AWS 許可支援。讀取/寫入 Lake Formation 註冊的 Delta 資料表時，不需要其他組態。若要讀取已註冊的 Delta AWS 資料表，Glue 任務 IAM 角色必須具有 SELECT 許可。若要寫入已註冊的 Delta AWS 資料表，Glue 任務 IAM 角色必須具有 SUPER 許可。若要進一步了解管理 Lake Formation 權限的資訊，請參閱[授予和撤銷 Data Catalog 資源的權限](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 Data Catalog
<a name="aws-glue-programming-etl-format-delta-lake-write"></a>

下列 AWS Glue ETL 指令碼示範如何將 Delta Lake 資料表寫入 Amazon S3，並將資料表註冊至 AWS Glue Data Catalog。

------
#### [ 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>")
```

------

## 範例：使用 Glue Data Catalog 從 Amazon S3 AWS 讀取 Delta Lake 資料表
<a name="aws-glue-programming-etl-format-delta-lake-read"></a>

下列 AWS Glue ETL 指令碼會讀取您在 中建立的 Delta Lake 資料表[範例：將 Delta Lake 資料表寫入 Amazon S3，並將其註冊到 AWS Glue Data Catalog](#aws-glue-programming-etl-format-delta-lake-write)。

------
#### [ 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()
  }
}
```

------

## 範例：使用 Glue Data Catalog 將 插入 Amazon S3 中的 `DataFrame` Delta Lake AWS 資料表
<a name="aws-glue-programming-etl-format-delta-lake-insert"></a>

此範例會將資料插入您在 [範例：將 Delta Lake 資料表寫入 Amazon S3，並將其註冊到 AWS Glue Data Catalog](#aws-glue-programming-etl-format-delta-lake-write) 中建立的 Delta Lake 資料表中。

**注意**  
此範例需要您設定`--enable-glue-datacatalog`任務參數，才能使用 AWS Glue Data Catalog 做為 Apache Spark Hive 中繼存放區。如需詳細資訊，請參閱 [在 Glue AWS 任務中使用任務參數](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 將 Delta Lake 資料表寫入 Amazon S3
<a name="aws-glue-programming-etl-format-delta_lake-write-spark"></a>

此範例會使用 Spark 將 Delta Lake 資料表寫入 Amazon S3。

------
#### [ 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 權限控制，您將需要先在 Lake Formation 中註冊資料表 Amazon S3 路徑。如需詳細資訊，請參閱 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html) (註冊 Amazon S3 位置)。您可以從 Lake Formation 主控台或使用 CLI AWS 註冊：

      ```
      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 目錄資料表。如需詳細資訊，請參閱[使用 Glue 爬蟲程式介紹原生 Delta Lake AWS 資料表支援](https://aws.amazon.com/blogs/big-data/introducing-native-delta-lake-table-support-with-aws-glue-crawlers/)。

      您也可以透過 Glue `CreateTable` API AWS 手動建立資料表。

1. 將 Lake Formation 許可授予 AWS Glue 任務 IAM 角色。您可以從 Lake Formation 主控台或使用 AWS CLI 授予許可。如需詳細資訊，請參閱[使用 Lake Formation 主控台和具名資源方法授予資料表權限](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html)。

1.  讀取在 Lake Formation 中註冊的 Delta 資料表。該程式碼與讀取未註冊之 Delta 資料表的程式碼相同。請注意，Glue AWS 任務 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 資料表的程式碼相同。請注意，Glue AWS 任務 IAM 角色需要具有 SUPER 許可才能成功寫入。

   根據預設，Glue AWS 會使用 `Append`做為 saveMode。您可以透過設定 `additional_options` 中的 saveMode 選項進行變更。如需有關 Delta 資料表之 saveMode 支援的資訊，請參閱[寫入資料表](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
   )
   ```

# 在 Glue AWS 中使用 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 資料表上執行讀取和寫入操作，或使用 Glue Data Catalog 使用 Iceberg AWS 資料表。還支援包括插入和所有 [Spark 查詢](https://iceberg.apache.org/docs/latest/spark-queries/) [Spark 寫入](https://iceberg.apache.org/docs/latest/spark-writes/)在內的其他操作。Iceberg 資料表不支援更新。

**注意**  
`ALTER TABLE … RENAME TO` 不適用於 AWS Glue 3.0 的 Apache Iceberg 0.13.1。

下表列出每個 Glue 版本中包含的 Iceberg AWS 版本。


****  

| 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` 任務參數的值。如需詳細資訊，請參閱[在 Glue AWS 任務中使用任務參數](aws-glue-programming-etl-glue-arguments.md)。
+ 為您的 Glue 任務建立名為 AWS `--conf`的金鑰，並將其設定為下列值。您也可以選擇在指令碼中使用 `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 鎖定管理員以確保原子交易。 AWS Glue 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 資料表具有自己的機制來啟用伺服器端加密。除了 Glue AWS 的安全組態之外，您應該啟用此組態。

若要在 Iceberg 資料表上啟用伺服器端加密，請檢閱 [Iceberg 文件](https://iceberg.apache.org/docs/latest/aws/#s3-server-side-encryption)中的指引。

**新增 Iceberg 跨區域的 Spark 組態**

若要使用 Glue Data Catalog 為 Iceberg 跨區域資料表存取新增額外的 Spark AWS 組態 AWS Lake Formation，請遵循下列步驟：

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 Data Catalog
<a name="aws-glue-programming-etl-format-iceberg-write"></a>

此範例指令碼示範如何將 Iceberg 資料表寫入 Amazon S3。此範例使用 [Iceberg AWS 整合](https://iceberg.apache.org/docs/latest/aws/)將資料表註冊至 AWS Glue Data Catalog。

------
#### [ 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 會直接執行此操作。Glue Data Catalog AWS 已預先設定為供 Spark 程式庫使用，做為 `glue_catalog`。資料目錄資料表由 *databaseName* 和 *tableName* 識別。如需 AWS Glue Data Catalog 的詳細資訊，請參閱 [中的資料探索和目錄編製 AWS Glue](catalog-and-crawler.md)。

如果您不是使用 AWS Glue Data Catalog，則需要透過 Spark APIs佈建目錄。如需詳細資訊，請參閱 Iceberg 文件中的 [Spark 組態](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()
```

------

## 範例：使用 Glue Data Catalog 從 Amazon S3 AWS 讀取 Iceberg 資料表
<a name="aws-glue-programming-etl-format-iceberg-read"></a>

此範例會讀取您在 [範例：將 Iceberg 資料表寫入 Amazon S3，並將其註冊到 AWS Glue Data Catalog](#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()
  }
}
```

------

## 範例：使用 Glue Data Catalog 將 `DataFrame`插入 Amazon S3 中的 Iceberg AWS 資料表
<a name="aws-glue-programming-etl-format-iceberg-insert"></a>

此範例會將資料插入您在 [範例：將 Iceberg 資料表寫入 Amazon S3，並將其註冊到 AWS Glue Data Catalog](#aws-glue-programming-etl-format-iceberg-write) 中建立的 Iceberg 資料表中。

**注意**  
此範例需要您設定`--enable-glue-datacatalog`任務參數，才能使用 AWS Glue Data Catalog 做為 Apache Spark Hive 中繼存放區。如需詳細資訊，請參閱 [在 Glue AWS 任務中使用任務參數](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 會直接執行此操作。Glue Data Catalog AWS 已預先設定為供 Spark 程式庫使用，做為 `glue_catalog`。資料目錄資料表由 *databaseName* 和 *tableName* 識別。如需 AWS Glue Data Catalog 的詳細資訊，請參閱 [中的資料探索和目錄編製 AWS Glue](catalog-and-crawler.md)。

如果您不是使用 AWS Glue Data Catalog，則需要透過 Spark APIs佈建目錄。如需詳細資訊，請參閱 Iceberg 文件中的 [Spark 組態](https://iceberg.apache.org/docs/latest/spark-configuration/)。

此範例使用 Spark 從資料目錄讀取 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 權限控制，您將需要先在 Lake Formation 中註冊資料表 Amazon S3 路徑。如需詳細資訊，請參閱 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html) (註冊 Amazon S3 位置)。您可以從 Lake Formation 主控台或使用 CLI AWS 註冊：

      ```
      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)
      ```

      您也可以透過 Glue `CreateTable` API AWS 手動建立資料表。如需詳細資訊，請參閱[建立 Apache Iceberg 資料表](https://docs.aws.amazon.com/lake-formation/latest/dg/creating-iceberg-tables.html)。
**注意**  
`UpdateTable` API 目前不支援 Iceberg 資料表格式作為操作的輸入。

1. 將 Lake Formation 權限授予任務 IAM 角色。您可以從 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
   )
   ```