

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

# 將 Iceberg 叢集與 Spark 搭配使用
<a name="emr-iceberg-use-spark-cluster"></a>

從 Amazon EMR 6.5.0 版開始，您可以將 Iceberg 與 Spark 叢集搭配使用，而無需包含引導操作。對於 Amazon EMR 6.4.0 版及更早版本，您可以使用引導操作來預先安裝所有必要的依存項目。

在本教學課程中，您會使用 AWS CLI 在 Amazon EMR Spark 叢集上使用 Iceberg。若要使用主控台建立已安裝 Iceberg 的叢集，請遵循[使用 Amazon Athena、Amazon EMR 和 AWS Glue 建置 Apache Iceberg 資料湖](https://aws.amazon.com/blogs//big-data/build-an-apache-iceberg-data-lake-using-amazon-athena-amazon-emr-and-aws-glue/)中的步驟進行。

## 建立 Iceberg 叢集
<a name="emr-iceberg-create-cluster"></a>

您可以使用 AWS 管理主控台、 AWS CLI 或 Amazon EMR API，建立已安裝 Iceberg 的叢集。在本教學課程中，您會使用 AWS CLI 在 Amazon EMR 叢集上使用 Iceberg。若要使用主控台建立已安裝 Iceberg 的叢集，請遵循[使用 Amazon Athena、Amazon EMR 和 AWS Glue 建置 Apache Iceberg 資料湖](https://aws.amazon.com/blogs//big-data/build-an-apache-iceberg-data-lake-using-amazon-athena-amazon-emr-and-aws-glue/)中的步驟進行。

若要在 Amazon EMR 上使用 Iceberg AWS CLI，請先使用下列步驟建立叢集。如需使用 指定 Iceberg 分類的資訊 AWS CLI，請參閱 [當您建立叢集 AWS CLI 時，使用 提供組態](emr-configure-apps-create-cluster.md#emr-configure-apps-create-cluster-cli)或 [在建立叢集時使用 Java SDK 提供組態](emr-configure-apps-create-cluster.md#emr-configure-apps-create-cluster-sdk)。

1. 使用下列內容建立 `configurations.json` 檔案：

   ```
   [{
       "Classification":"iceberg-defaults",
       "Properties":{"iceberg.enabled":"true"}
   }]
   ```

1. 接下來，使用下列組態建立叢集。將範例 Amazon S3 儲存貯體路徑和子網路 ID 取代為您自己的值。

   ```
   aws emr create-cluster --release-label emr-6.5.0 \
   --applications Name=Spark \
   --configurations file://configurations.json \
   --region us-east-1 \
   --name My_Spark_Iceberg_Cluster \
   --log-uri s3://amzn-s3-demo-bucket/ \
   --instance-type m5.xlarge \
   --instance-count 2 \
   --service-role EMR_DefaultRole_V2 \ 
   --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole,SubnetId=subnet-1234567890abcdef0
   ```

或者，您可以建立包含 Spark 應用程式的 Amazon EMR 叢集，並將檔案 `/usr/share/aws/iceberg/lib/iceberg-spark3-runtime.jar` 作為 Spark 作業中的 JAR 依存項目。如需詳細資訊，請參閱[提交應用程式](https://spark.apache.org/docs/latest/submitting-applications.html#submitting-applications)。

若要將 jar 作為依存項目包含在 Spark 作業中，請將下列組態屬性新增至 Spark 應用程式：

```
--conf "spark.jars=/usr/share/aws/iceberg/lib/iceberg-spark3-runtime.jar"
```

如需有關 Spark 作業相依性的詳細資訊，請參閱 Apache Spark 文件[在 Kubernetes 上執行 Spark](https://spark.apache.org/docs/latest/running-on-kubernetes.html) 中的[相依性管理](https://spark.apache.org/docs/latest/running-on-kubernetes.html#dependency-management)。

## 初始化 Iceberg 的 Spark 工作階段
<a name="emr-iceberg-initialize-spark-session"></a>

下列範例示範如何啟動互動式 Spark Shell、使用 Spark 提交，或透過 Amazon EMR Notebooks 在 Amazon EMR 上使用 Iceberg。

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

1. 使用 SSH 連接至主節點。如需詳細資訊，請參閱《Amazon EMR 管理指南》**中的[使用 SSH 連接至主節點](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)。

1. 輸入以下命令啟動 Spark shell。若要使用 PySpark Shell，請將 `spark-shell` 取代為 `pyspark`。

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

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

1. 使用 SSH 連接至主節點。如需詳細資訊，請參閱《Amazon EMR 管理指南》**中的[使用 SSH 連接至主節點](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)。

1. 輸入下列命令啟動 Iceberg 的 Spark 工作階段。

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

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

若要使用 EMR Studio 筆記本初始化 Spark 工作階段，請使用 Amazon EMR Notebooks 中的 `%%configure` 魔法命令來設定 Spark 工作階段，如下列範例所示。如需詳細資訊，請參閱《Amazon EMR 管理指南》**中的[使用 EMR Notebooks 魔法](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-studio-magics.html#emr-magics)。

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

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

若要使用 CLI 初始化 Spark 叢集並設定所有 Spark Iceberg 工作階段預設組態，請執行下列範例。如需使用 AWS CLI 和 Amazon EMR API 指定組態分類的詳細資訊，請參閱[設定應用程式](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps.html)。

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

------

## 寫入 Iceberg 資料表
<a name="emr-iceberg-write-to-table"></a>

下列範例顯示如何建立 DataFrame 並將其寫入為 Iceberg 資料集。這些範例示範使用 Spark shell 來處理資料集，同時以預設的 hadoop 使用者身分使用 SSH 連接至主節點。

**注意**  
若要將程式碼範例貼到 Spark Shell 中，請在提示字元中鍵入 `:paste`、貼上範例，然後按 `CTRL+D`。

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

Spark 包含 Python 型 Shell `pyspark`，您可以使用該 Shell 來開發以 Python 撰寫之 Spark 程式的原型。在主節點上調用 `pyspark`。

```
## Create a DataFrame.
data = spark.createDataFrame([
 ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
 ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
 ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
 ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z")
],["id", "creation_date", "last_update_time"])

## Write a DataFrame as a Iceberg dataset to the Amazon S3 location.
spark.sql("""CREATE TABLE IF NOT EXISTS dev.db.iceberg_table (id string,
creation_date string,
last_update_time string)
USING iceberg
location 's3://amzn-s3-demo-bucket/example-prefix/db/iceberg_table'""")

data.writeTo("dev.db.iceberg_table").append()
```

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

```
import org.apache.spark.sql.SaveMode
import org.apache.spark.sql.functions._

// Create a DataFrame.
val data = Seq(
("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
("103", "2015-01-01", "2015-01-01T13:51:40.519832Z")
).toDF("id", "creation_date", "last_update_time")

// Write a DataFrame as a Iceberg dataset to the Amazon S3 location.
spark.sql("""CREATE TABLE IF NOT EXISTS dev.db.iceberg_table (id string,
creation_date string,
last_update_time string)
USING iceberg
location 's3://amzn-s3-demo-bucket/example-prefix/db/iceberg_table'""")

data.writeTo("dev.db.iceberg_table").append()
```

------

## 從 Iceberg 資料表讀取
<a name="emr-iceberg-read-from-table"></a>

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

```
df = spark.read.format("iceberg").load("dev.db.iceberg_table")
df.show()
```

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

```
val df = spark.read.format("iceberg").load("dev.db.iceberg_table")
df.show()
```

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

```
SELECT * from dev.db.iceberg_table LIMIT 10
```

------

## 搭配 Spark Iceberg 使用 AWS Glue Data Catalog
<a name="emr-iceberg-glue-catalog-config-spark"></a>

您可以從 Spark Iceberg 連線至 AWS Glue Data Catalog。本節顯示用於連線的不同命令。

### 連接至預設區域中的預設 AWS Glue 目錄
<a name="emr-iceberg-glue-catalog-config-spark"></a>

此範例示範如何使用 Glue 目錄類型進行連線。如果您未指定目錄 ID，則會使用預設值：

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

### 使用特定目錄 ID AWS 連線至 Glue 目錄
<a name="emr-iceberg-glue-catalog-config-spark"></a>

此範例示範如何使用目錄 ID 進行連線：

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

此命令可用於連接到不同帳戶中的 AWS Glue 目錄、RMS 目錄或聯合目錄。

## 搭配 Spark Iceberg 使用 Iceberg REST Catalog (IRC)
<a name="emr-iceberg-rest-catalog-config"></a>

以下各節詳細說明如何設定 Iceberg 與目錄的整合。

### 連接至 AWS Glue Data Catalog IRC 端點
<a name="emr-iceberg-rest-catalog-config-gdc"></a>

以下顯示使用 Iceberg REST 的範例`spark-submit`命令：

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

若要在已啟用執行期角色的叢集上使用它，需要下列額外的 Spark 組態設定：

```
"spark.hadoop.fs.s3.credentialsResolverClass": "software.amazon.glue.GlueTableCredentialsResolver",
"spark.hadoop.catalog-impl": "org.apache.iceberg.aws.glue.GlueCatalog",
"spark.hadoop.glue.id": glue catalog ID
"spark.hadoop.glue.endpoint": "glue endpoint"
```

如需每個區域的 AWS Glue 端點 URL 清單，請參閱 [AWS Glue 端點和配額](https://docs.aws.amazon.com/general/latest/gr/glue.html)。

### 連接至任意 IRC 端點
<a name="emr-iceberg-rest-catalog-config-arbitrary"></a>

以下顯示使用 IRC 端點的範例`spark-submit`命令：

```
spark-submit \
    --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
    --conf spark.sql.catalog.my_catalog.warehouse=warehouse name \
    --conf spark.sql.catalog.my_catalog.type=rest \
    --conf spark.sql.catalog.my_catalog.uri=your rest endpoint \
    --conf spark.sql.defaultCatalog=my_catalog \
    --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
```

## 使用 Iceberg SparkCatalog 與 SparkSessionCatalog 時的組態差異
<a name="emr-iceberg-spark-catalog"></a>

Iceberg 提供兩種建立 Spark Iceberg 目錄的方式。您可以將 Spark 組態設定為 `SparkCatalog`或 `SparkSessionCatalog`。

### 使用 Iceberg SparkCatalog
<a name="emr-iceberg-spark-catalog-spark-catalog"></a>

以下顯示使用 **SparkCatalog** 做為 Spark Iceberg 目錄的 命令：

```
spark-shell \
--conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://amzn-s3-demo-bucket1/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.defaultCatalog=my_catalog
```

此方法的考量事項：
+ 您可以存取 Iceberg 資料表，但無法存取其他資料表。
+ 目錄名稱不能是 **spark\$1catalog**。這是 Spark 中初始目錄的名稱。它一律會連線至 Hive 中繼存放區。除非使用者使用 覆寫它，否則它是 Spark 中的預設目錄`spark.sql.defaultCatalog`。
+ 您可以將 `spark.sql.defaultCatalog` 設定為目錄名稱，讓 成為預設目錄。

### 使用 Iceberg SparkSessionCatalog
<a name="emr-iceberg-spark-catalog-spark-session"></a>

以下顯示使用 **SparkSessionCatalog** 做為 Spark Iceberg 目錄的 命令：

```
spark-shell \
    --conf spark.sql.catalog.spark_catalog=org.apache.iceberg.spark.SparkSessionCatalog \
    --conf spark.sql.catalog.spark_catalog.warehouse=s3://amzn-s3-demo-bucket1/prefix \
    --conf spark.sql.catalog.spark_catalog.type=glue
```

此方法的考量事項：
+ 如果找不到資料表做為 Iceberg 資料表，Spark 會嘗試查看其是否為 Hive 中繼存放區中的資料表。如需詳細資訊[，請參閱使用 AWS Glue Data Catalog 做為 Hive 的目錄](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hive-metastore-glue.html)。
+ 目錄名稱必須是 **spark\$1catalog**。

## 使用 Iceberg Spark 延伸模組
<a name="emr-iceberg-spark-catalog-extensions"></a>

Iceberg `org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions` 提供使用者可以透過 Spark 擴充功能組態 設定的 Spark 擴充功能`spark.sql.extensions`。延伸項目可啟用重要 Iceberg 功能，例如資料列層級 DELETE、UPDATE 和 MERGE、Iceberg 特定的 Spark 資料定義語言陳述式和程序，例如壓縮、快照過期、分支和標記等。如需詳細資訊，請參閱下列內容：
+ Iceberg Spark 寫入延伸模組：[Spark 寫入](https://iceberg.apache.org/docs/nightly/spark-writes/)
+ Iceberg Spark DDL 延伸模組：[ALTER TABLE SQL 延伸模組](https://iceberg.apache.org/docs/nightly/spark-ddl/#alter-table-sql-extensions/)
+ Iceberg Spark 程序延伸：[Spark 程序](https://iceberg.apache.org/docs/nightly/spark-ddl/#alter-table-sql-extensions/)

## 將 Iceberg 與 Spark 搭配使用的考量
<a name="spark-considerations-catalog"></a>
+ 依預設，Amazon EMR 6.5.0 不支援 Iceberg 在 Amazon EMR on EKS 上執行。Amazon EMR 6.5.0 自訂映像可用，以便您可以將 `--jars local:///usr/share/aws/iceberg/lib/iceberg-spark3-runtime.jar` 作為 `spark-submit` 參數傳遞，以在 Amazon EMR on EKS 上建立 Iceberg 資料表。如需詳細資訊，請參閱《Amazon EMR on EKS 開發指南》**中的[使用自訂映像在 Amazon EMR 中提交 Spark 工作負載](https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/docker-custom-images-steps.html#docker-custom-images-submit)。您還可以聯絡 支援 尋求協助。從 Amazon EMR 6.6.0 開始，Amazon EMR on EKS 支援 Iceberg。
+ 使用 AWS Glue 做為 Iceberg 的目錄時，請確定您在其中建立資料表的資料庫存在於 Glue AWS 中。如果您使用的是 服務， AWS Lake Formation 但無法載入目錄，請確定您有權存取服務來執行 命令。
+ 如果您使用 Iceberg SparkSessionCatalog，如中所述[使用 Iceberg SparkCatalog 與 SparkSessionCatalog 時的組態差異](#emr-iceberg-spark-catalog)，除了設定 Spark Iceberg [AWS Glue Data Catalog 設定之外，您還必須遵循設定 Glue Data Catalog 中所述的組態步驟做為 Apache Hive 中繼存放](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-hive-metastore-glue.html)區 AWS 。