

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

# 使用具有 Iceberg 的叢集
<a name="emr-iceberg-use-cluster"></a>

本章節包含有關將 Iceberg 與 Spark、Trino、Flink 及 Hive 搭配使用的資訊。

# 將 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 。

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

從 Amazon EMR 6.6.0 版開始，您可以將 Iceberg 與 Trino 叢集搭配使用。

在本教學課程中，您會使用 AWS CLI 在 Amazon EMR Trino 叢集上使用 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-trino"></a>

若要在 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` 檔案。例如，如果您想要使用 Hive 中繼存放區作為型錄，您的檔案應具有下列內容。

   ```
   [
     {
       "Classification": "trino-connector-iceberg",
       "Properties": {
         "connector.name": "iceberg",
         "hive.metastore.uri": "thrift://localhost:9083"
       }
     }
   ]
   ```

   如果您想要使用 AWS Glue Data Catalog 做為您的存放區，您的檔案應具有下列內容。

   ```
   [
     {
       "Classification": "trino-connector-iceberg",
       "Properties": {
         "connector.name": "iceberg",
         "iceberg.catalog.type": "glue"
       }
     }
   ]
   ```

   從 Amazon EMR 7.7.0 開始，包含 屬性 *fs.native-s3.enabled=true*

   ```
   [
     { 
       "Classification": "trino-connector-iceberg",
       "Properties": {
         "connector.name": "iceberg",
         "iceberg.catalog.type": "glue",
         "fs.native-s3.enabled": "true"
       }           
     }                 
   ]
   ```

1. 使用下列組態建立叢集，以您自己的組態取代範例 Amazon S3 儲存貯體路徑和金鑰名稱。

   ```
   aws emr create-cluster --release-label emr-6.7.0 \
   --applications Name=Trino \
   --region us-east-1 \
   --name My_Trino_Iceberg_Cluster \
   --log-uri s3://amzn-s3-demo-bucket \
   --configurations file://configurations.json \
   --instance-groups InstanceGroupType=MASTER,InstanceCount=1,InstanceType=c3.4xlarge InstanceGroupType=CORE,InstanceCount=3,InstanceType=c3.4xlarge \ 
   --use-default-roles \
   --ec2-attributes KeyName=<key-name>
   ```

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

若要初始化 Trino 工作階段，請執行下列命令。

```
trino-cli --catalog iceberg
```

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

使用下列 SQL 命令建立並寫入至資料表。

```
trino> SHOW SCHEMAS;
trino> CREATE TABLE default.iceberg_table (
            id int,
            data varchar,
            category varchar)
       WITH (
            format = 'PARQUET',
            partitioning = ARRAY['category', 'bucket(id, 16)'],
            location = 's3://amzn-s3-demo-bucket/<prefix>')
          
trino> INSERT INTO default.iceberg_table VALUES (1,'a','c1'), (2,'b','c2'), (3,'c','c3');
```

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

若要從 Iceberg 資料表讀取，請執行下列命令。

```
trino> SELECT * from default.iceberg_table;
```

## 將 Iceberg 與 Trino 搭配使用的考量
<a name="trino-considerations"></a>
+ Amazon EMR 6.5 不會以原生方式提供對 Iceberg 的 Trino Iceberg Catalog 支援。Trino 需要使用 Iceberg v0.11，因此建議為 Trino 啟動獨立於 Spark 叢集的 Amazon EMR 叢集，並在該叢集上包含 Iceberg v0.11。
+ 使用 AWS Glue 做為 Iceberg 的目錄時，請確定您在其中建立資料表的資料庫存在於 Glue AWS 中。如果您使用的是 服務， AWS Lake Formation 但無法載入目錄，請確定您有權存取服務來執行 命令。
+ Iceberg Glue 整合不適用於 Redshift 受管儲存目錄。

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

從 Amazon EMR 6.9.0 版開始，您可以將 Iceberg 與 Flink 叢集搭配使用，而無需使用開放原始碼 Iceberg Flink 整合時所需的設定步驟。

## 建立 Iceberg 叢集
<a name="creating-iceberg-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)。建立稱為 `configurations.json` 的檔案，其中具有下列內容：

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

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

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

或者，您可以建立其中具有 Flink 應用程式的 Amazon EMR 6.9.0 叢集，並將檔案 `/usr/share/aws/iceberg/lib/iceberg-flink-runtime.jar` 作為 Flink 作業中的 JAR 依存項目。

## 使用 Flink SQL 用戶端
<a name="using-flink-sql-client"></a>

SQL 用戶端指令碼位於 `/usr/lib/flink/bin` 下。您可以使用下列命令執行指令碼：

```
flink-yarn-session -d # starting the Flink YARN Session in detached mode
./sql-client.sh
```

這將啟動 Flink SQL Shell。

## Flink 範例
<a name="flink-examples"></a>

### 建立 Iceberg 資料表
<a name="create-iceberg-table"></a>

**Flink SQL**

```
CREATE CATALOG glue_catalog WITH (
   'type'='iceberg',
   'warehouse'='<WAREHOUSE>',
   'catalog-impl'='org.apache.iceberg.aws.glue.GlueCatalog',
    'io-impl'='org.apache.iceberg.aws.s3.S3FileIO'
 );

USE CATALOG  glue_catalog;

CREATE DATABASE IF NOT EXISTS <DB>;

USE <DB>;

CREATE TABLE IF NOT EXISTS `glue_catalog`.`<DB>`.`sample` (id int, data string);
```

**資料表 API**

```
EnvironmentSettings settings =
                EnvironmentSettings.newInstance().inBatchMode().build();

TableEnvironment tEnv = TableEnvironment.create(settings);

String warehouse = "<WAREHOUSE>";
String db = "<DB>";

tEnv.executeSql(
                "CREATE CATALOG glue_catalog WITH (\n"
                        + "   'type'='iceberg',\n"
                        + "   'warehouse'='"
                        + warehouse
                        + "',\n"
                        + "   'catalog-impl'='org.apache.iceberg.aws.glue.GlueCatalog',\n"
                        + "   'io-impl'='org.apache.iceberg.aws.s3.S3FileIO'\n"
                        + " );");

tEnv.executeSql("USE CATALOG  glue_catalog;");
tEnv.executeSql("CREATE DATABASE IF NOT EXISTS " + db + ";");
tEnv.executeSql("USE " + db + ";");
tEnv.executeSql(
        "CREATE TABLE `glue_catalog`.`" + db + "`.`sample` (id bigint, data string);");
```

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

**Flink SQL**

```
INSERT INTO `glue_catalog`.`<DB>`.`sample` values (1, 'a'),(2,'b'),(3,'c');
```

**資料表 API**

```
tEnv.executeSql(
        "INSERT INTO `glue_catalog`.`"
                + db
                + "`.`sample` values (1, 'a'),(2,'b'),(3,'c');");
```

**資料串流 API**

```
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

final StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

String db = "<DB Name>";

String warehouse = "<Warehouse Path>";

GenericRowData rowData1 = new GenericRowData(2);
rowData1.setField(0, 1L);
rowData1.setField(1, StringData.fromString("a"));

DataStream<RowData> input = env.fromElements(rowData1);

Map<String, String> props = new HashMap<();
props.put("type", "iceberg");
props.put("warehouse", warehouse);
props.put("io-impl", "org.apache.iceberg.aws.s3.S3FileIO");

CatalogLoader glueCatlogLoader =
        CatalogLoader.custom(
                "glue",
                props,
                new Configuration(),
                "org.apache.iceberg.aws.glue.GlueCatalog");

TableLoader tableLoader =
        TableLoader.fromCatalog(glueCatlogLoader, TableIdentifier.of(db, "sample"));

DataStreamSink<Void> dataStreamSink =
        FlinkSink.forRowData(input).tableLoader(tableLoader).append();

env.execute("Datastream Write");
```

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

**Flink SQL**

```
SELECT * FROM `glue_catalog`.`<DB>`.`sample`;
```

**資料表 API**

```
Table result = tEnv.sqlQuery("select * from `glue_catalog`.`" + db + "`.`sample`;");
```

**資料串流 API**

```
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

final StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

String db = "<DB Name>";

String warehouse = "<Warehouse Path>";

Map<String, String> props = new HashMap<>();
props.put("type", "iceberg");
props.put("warehouse", warehouse);
props.put("io-impl", "org.apache.iceberg.aws.s3.S3FileIO");

CatalogLoader glueCatlogLoader =
        CatalogLoader.custom(
                "glue",
                props,
                new Configuration(),
                "org.apache.iceberg.aws.glue.GlueCatalog");
                
TableLoader tableLoader =
        TableLoader.fromCatalog(glueCatlogLoader, TableIdentifier.of(db, "sample"));

DataStream<RowData> batch =
                FlinkSource.forRowData().env(env).tableLoader(tableLoader).streaming(false).build();

batch.print().name("print-sink");
```

## 使用 Hive 型錄
<a name="using-hive-catalog"></a>

請確保如 [將 Flink 與 Hive Metastore 和 Glue Catalog 搭配使用](flink-configure.md#flink-configure-hive) 中所述解析 Flink 和 Hive 依存項目。

## 執行 Flink 作業
<a name="running-flink-job"></a>

向 Flink 提交作業的一種方法是使用每個作業的 Flink YARN 作業階段。這可以使用下列命令來啟動：

```
sudo flink run -m yarn-cluster -p 4 -yjm 1024m -ytm 4096m $JAR_FILE_NAME
```

## 將 Iceberg 與 Flink 搭配使用的考量
<a name="flink-considerations"></a>
+ 使用 AWS Glue 做為 Iceberg 的目錄時，請確定您在其中建立資料表的資料庫存在於 Glue AWS 中。如果您使用的是 服務， AWS Lake Formation 但無法載入目錄，請確定您有權存取服務來執行 命令。
+ Iceberg Glue 整合不適用於 Redshift 受管儲存目錄。

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

透過 Amazon EMR 6.9.0 版及更高版本，您可以將 Iceberg 與 Hive 叢集搭配使用，而無需執行開放原始碼 Iceberg Hive 整合所需的設定步驟。對於 Amazon EMR 6.8.0 版及更早版本，您可以使用引導操作來安裝 `iceberg-hive-runtime` jar，以設定 Hive for Iceberg 支援。

Amazon EMR 6.9.0 包括 [Hive 3.1.3 與 Iceberg 0.14.1 整合](https://iceberg.apache.org/releases/#0140-release)的所有功能，還包括 Amazon EMR 新增的功能，例如在執行期自動選取支援的執行引擎 (EKS 6.9.0 上的 Amazon EMR)。

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

您可以使用 AWS 管理主控台、 AWS CLI 或 Amazon EMR API，建立已安裝 Iceberg 的叢集。在本教學課程中，您會使用 AWS CLI 在 Amazon EMR 叢集上使用 Iceberg。若要使用主控台建立已安裝 Iceberg 的叢集，請遵循[使用 Amazon Athena、Amazon EMR 和 AWS Glue 建置 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，請先使用下列步驟建立叢集。如需使用 AWS CLI 或 Java 開發套件指定 Iceberg 分類的資訊，請參閱 [當您建立叢集 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)。建立名為 `configurations.json` 且具有下列內容的檔案：

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

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

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

Hive Iceberg 叢集執行下列操作：
+ 在 Hive 中載入 Iceberg Hive 執行期 jar，並為 Hive 引擎啟用 Iceberg 相關的組態。
+ 啟用 Amazon EMR Hive 的動態執行引擎選擇，以防止使用者設定支援的執行引擎實現 Iceberg 相容性。

**注意**  
Hive Iceberg 叢集目前不支援 AWS Glue Data Catalog。預設 Iceberg 型錄為 `HiveCatalog`，它對應於為 Hive 環境設定的中繼存放區。如需目錄管理的詳細資訊，請參閱 [Apache Hive 文件](https://cwiki.apache.org/confluence/display/HIVE)中的[使用 HCatalog](https://cwiki.apache.org/confluence/display/Hive/HCatalog+UsingHCat#HCatalogUsingHCat-UsingHCatalog)。

## 功能支援
<a name="feature-support"></a>

Amazon EMR 6.9.0 支援 Hive 3.1.3 和 Iceberg 0.14.1。此功能支援僅限於 Hive 3.1.2 和 3.1.3 的 Iceberg 相容功能。支援下列命令：
+ 使用 Amazon EMR 6.9.0 版至 6.12.x 版，您必須將 `libfb303` jar 包含在 Hive `auxlib` 目錄中。使用下列命令將其包含在內：

  ```
  sudo /usr/bin/ln -sf /usr/lib/hive/lib/libfb303-*.jar /usr/lib/hive/auxlib/libfb303.jar
  ```

  使用 Amazon EMR 6.13 版及更高版本，`libfb303` jar 會自動透過符號連結至 Hive `auxlib` 目錄。
+ **建立資料表**
  + **非分割的資料表** – 可以透過提供儲存處理常式在 Hive 中建立外部資料表，如下所示：

    ```
    CREATE EXTERNAL TABLE x (i int) STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
    ```
  + **分割的資料表** – 可以在 Hive 中建立外部分割的資料表，如下所示：

    ```
    CREATE EXTERNAL TABLE x (i int) PARTITIONED BY (j int) STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
    ```
**注意**  
Hive 3 不支援 ORC/AVRO/PARQUET 的 `STORED AS` 檔案格式。預設且唯一的選項是 Parquet。
+ **捨棄資料表** – `DROP TABLE` 命令用於捨棄資料表，如下列範例所示：

  ```
  DROP TABLE [IF EXISTS] table_name [PURGE];
  ```
+ **讀取資料表** – `SELECT` 陳述式可用於讀取 Hive 中的 Iceberg 資料表，如下列範例所示。支援的執行引擎為 MR 和 Tez。

  ```
  SELECT * FROM table_name
  ```

  如需有關 Hive 的 select 語法的資訊，請參閱 [LanguageManual Select](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Select)。如需有關 Hive 中 Iceberg 資料表的 select 陳述式的資訊，請參閱 [Apache Iceberg Select](https://iceberg.apache.org/docs/latest/hive/#select)。
+ **插入到資料表** – HiveQL 的 `INSERT INTO` 陳述式僅適用於支援 Map Reduce 執行引擎的 Iceberg 資料表。Amazon EMR 使用者無需明確地設定執行引擎，因為 Amazon EMR Hive 會在執行期為 Iceberg 資料表選取引擎。
  + **單一資料表插入** – 範例：

    ```
    INSERT INTO table_name VALUES ('a', 1);
    INSERT INTO table_name SELECT...;
    ```
  + **多資料表插入** – 支援非原子多資料表插入到陳述式。範例：

    ```
    FROM source
     INSERT INTO table_1 SELECT a, b
     INSERT INTO table_2 SELECT c,d;
    ```

從 Amazon EMR 7.3.0 開始，Hive with Iceberg 支援 AWS Glue Data Catalog 作為中繼存放區。若要使用 AWS Glue Data Catalog 做為中繼存放區，請設定下列屬性。

```
SET iceberg.catalog.<catalog_name>.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog;
```

或者，您也可以設定下列屬性。

```
SET iceberg.catalog.<catalog_name>.type=glue;
```

然後，您可以使用下列範例建立資料表。

```
CREATE EXTERNAL TABLE table_name (col1 type1, col2 type2,..)
ROW FORMAT SERDE 'org.apache.iceberg.mr.hive.HiveIcebergSerDe'
STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
location '<location>'
TBLPROPERTIES ('table_type'='iceberg', 'iceberg.catalog'='<catalog_name>');
```

## 將 Iceberg 與 Hive 搭配使用的考量
<a name="hive-considerations"></a>
+ Iceberg 支援下列查詢類型：
  + 建立資料表
  + 卸除資料表
  + 插入到資料表
  + 讀取資料表
+ DML (資料處理語言) 操作僅支援 MR (MapReduce) 執行引擎，而 MR 在 Hive 3.1.3 中已棄用。
+ 對於 7.3.0 之前的 Amazon EMR，搭配 Hive 的 Iceberg 目前不支援 AWS Glue Data Catalog。
+ 錯誤處理不夠強大。在組態錯誤的情況下，插入到查詢可能會成功完成。但是，無法更新中繼資料可能會導致資料遺失。
+ Iceberg Glue 整合不適用於 Redshift 受管儲存目錄。