

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

# 支援開放式資料表格式
<a name="emr-lf-fgac1"></a>

當您使用 Spark SQL 讀取和寫入資料時，Amazon EMR 6.15.0 版和更高版本包括支援以 AWS Lake Formation Hive 資料表、Apache Iceberg、Apache Hudi 和 Delta Lake 為基礎的精細存取控制。Amazon EMR 使用 Apache Hudi 來支援資料表、資料列、資料欄和儲存格層級存取控制。Amazon EMR 6.15.0 版及更高版本包括支援根據 AWS Lake Formation 的資料列、資料欄或儲存格層級的精細存取控制。從 EMR 7.12 開始，使用 Lake Formation 提供的登入資料，Apache Hive、Apache Iceberg 和 Delta Lake 資料表支援修改資料表資料的 DML 和 DDL 操作。

本節中的主題涵蓋如何透過 EMR Spark 任務或具有精細存取控制的互動式工作階段，以開放資料表格式存取 Lake Formation 註冊的資料表。

## 許可要求
<a name="emr-lf-perm"></a>

### 資料表未在 中註冊 AWS Lake Formation
<a name="emr-lf-tbl-reg"></a>

對於未向 註冊的資料表 AWS Lake Formation，任務執行時間角色會同時存取 AWS Glue Data Catalog 和 Amazon S3 中的基礎資料表資料。這需要任務執行時間角色才能同時擁有 Glue 和 Amazon S3 AWS 操作的適當 IAM 許可。

### 在 中註冊的資料表 AWS Lake Formation
<a name="emr-lf-tbl-not-reg"></a>

對於向 註冊的資料表 AWS Lake Formation，任務執行時間角色會存取 AWS Glue Data Catalog 中繼資料，而 Lake Formation 提供的臨時憑證則會存取 Amazon S3 中的基礎資料表資料。執行 操作所需的 Lake Formation 許可取決於 Spark 任務啟動的 AWS Glue Data Catalog 和 Amazon S3 API 呼叫，並可以摘要如下：
+ **DESCRIBE** 許可允許執行期角色讀取 Data Catalog 中的資料表或資料庫中繼資料
+ **ALTER** 許可允許執行期角色修改 Data Catalog 中的資料表或資料庫中繼資料
+ **DROP** 許可允許執行時間角色從 Data Catalog 刪除資料表或資料庫中繼資料
+ **SELECT** 許可允許執行期角色從 Amazon S3 讀取資料表資料
+ **INSERT** 許可允許執行期角色將資料表資料寫入 Amazon S3
+ **DELETE** 許可允許執行時間角色從 Amazon S3 刪除資料表資料
**注意**  
當 Spark 任務呼叫 AWS Glue 擷取資料表中繼資料和 Amazon S3 擷取資料表資料時，Lake Formation 會延遲評估許可。在 Spark 進行需要缺少許可的 AWS Glue 或 Amazon S3 呼叫之前，使用執行時間角色且許可不足的任務不會失敗。

**注意**  
在下列支援的資料表矩陣中：  
標示為 **Supported** 的操作只會使用 Lake Formation 登入資料來存取向 Lake Formation 註冊之資料表的資料表資料。如果 Lake Formation 許可不足，操作將不會回復為執行時間角色登入資料。對於未向 Lake Formation 註冊的資料表，任務執行期角色登入資料會存取資料表資料。
在 **Amazon S3 位置上標記為支援 IAM 許可**的操作不會使用 Lake Formation 登入資料來存取 Amazon S3 中的基礎資料表資料。若要執行這些操作，任務執行時間角色必須具有存取資料表資料的必要 Amazon S3 IAM 許可，無論資料表是否已向 Lake Formation 註冊。

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

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/emr/latest/ManagementGuide/emr-lf-fgac1.html)

------
#### [ Iceberg ]

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/emr/latest/ManagementGuide/emr-lf-fgac1.html)

**Iceberg 的 Spark 組態：**如果您想要使用 Iceberg 格式，請設定下列組態。`DB_LOCATION` 將 取代為 Iceberg 資料表所在的 Amazon S3 路徑，並將區域和帳戶 ID 預留位置取代為您自己的值。

```
spark-sql \
--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
--conf spark.sql.catalog.spark_catalog=org.apache.iceberg.spark.SparkSessionCatalog 
--conf spark.sql.catalog.spark_catalog.warehouse=s3://DB_LOCATION
--conf spark.sql.catalog.spark_catalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog 
--conf spark.sql.catalog.spark_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO
--conf spark.sql.catalog.spark_catalog.glue.account-id=ACCOUNT_ID
--conf spark.sql.catalog.spark_catalog.glue.id=ACCOUNT_ID
--conf spark.sql.catalog.spark_catalog.client.region=AWS_REGION
```

如果您想要在舊版 EMR 上使用 Iceberg 格式，請改用下列命令：

```
spark-sql \
--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,com.amazonaws.emr.recordserver.connector.spark.sql.RecordServerSQLExtension  
--conf spark.sql.catalog.spark_catalog=org.apache.iceberg.spark.SparkCatalog 
--conf spark.sql.catalog.spark_catalog.warehouse=s3://DB_LOCATION
--conf spark.sql.catalog.spark_catalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog 
--conf spark.sql.catalog.spark_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO  
--conf spark.sql.catalog.spark_catalog.glue.account-id=ACCOUNT_ID
--conf spark.sql.catalog.spark_catalog.glue.id=ACCOUNT_ID
--conf spark.sql.catalog.spark_catalog.client.assume-role.region=AWS_REGION
--conf spark.sql.catalog.spark_catalog.lf.managed=true
```

**範例**：

以下是使用 Iceberg 資料表的一些範例：

```
-- Create an Iceberg table
CREATE TABLE my_iceberg_table (
    id BIGINT,
    name STRING,
    created_at TIMESTAMP
) USING ICEBERG;

-- Insert data
INSERT INTO my_iceberg_table VALUES (1, 'Alice', current_timestamp());

-- Query the table
SELECT * FROM my_iceberg_table;
```

------
#### [ Hudi ]

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/emr/latest/ManagementGuide/emr-lf-fgac1.html)

**Hudi 的 Spark 組態：**

若要在 EMR 7.10 或更新版本上啟動 Spark shell，請使用下列命令：

```
spark-sql
--jars /usr/lib/hudi/hudi-spark-bundle.jar \
--conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog \
--conf spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension
```

若要在舊版 EMR 上啟動 Spark shell，請改用下列命令：

```
spark-sql
--jars /usr/lib/hudi/hudi-spark-bundle.jar \
--conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
--conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog \
--conf spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension,com.amazonaws.emr.recordserver.connector.spark.sql.RecordServerSQLExtension  \
--conf spark.sql.catalog.spark_catalog.lf.managed=true
```

**範例**：

以下是使用 Hudi 資料表的一些範例：

```
-- Create a Hudi table
CREATE TABLE my_hudi_table (
    id BIGINT,
    name STRING,
    created_at TIMESTAMP
) USING HUDI
TBLPROPERTIES (
    'type' = 'cow',
    'primaryKey' = 'id'
);

-- Insert data
INSERT INTO my_hudi_table VALUES (1, 'Alice', current_timestamp());

-- Query the latest snapshot
SELECT * FROM my_hudi_table;
```

若要查詢copy-on-write資料表的最新快照：

```
SELECT * FROM my_hudi_cow_table
```

```
spark.read.table("my_hudi_cow_table")
```

若要查詢 `MOR` 資料表的最新壓縮資料，您可以查詢字尾為 `_ro` 的讀取優化資料表：

```
SELECT * FROM my_hudi_mor_table_ro
```

```
spark.read.table("my_hudi_mor_table_ro")
```

------
#### [ Delta Lake ]

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/emr/latest/ManagementGuide/emr-lf-fgac1.html)

**Delta Lake 的 Spark 組態：**

若要在 EMR 7.10 及更高版本上使用 Delta Lake 搭配 Lake Formation，請執行下列命令：

```
spark-sql \
   --conf spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension \
  --conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog
```

若要在 EMR 6.15 到 7.9 上使用 Delta Lake 搭配 Lake Formation，請執行下列動作

```
spark-sql \
  --conf spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension,com.amazonaws.emr.recordserver.connector.spark.sql.RecordServerSQLExtension \
  --conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog \
  --conf spark.sql.catalog.spark_catalog.lf.managed=true
```

如果您希望 Lake Formation 使用記錄伺服器來管理您的 Spark 目錄，請將 `spark.sql.catalog.<managed_catalog_name>.lf.managed` 設為 true。

**範例**：

以下是使用 Delta Lake 資料表的一些範例：

```
-- Create a Delta Lake table
CREATE TABLE my_delta_table (
    id BIGINT,
    name STRING,
    created_at TIMESTAMP
) USING DELTA;

-- Insert data
INSERT INTO my_delta_table VALUES (1, 'Alice', current_timestamp());

-- Query the table
SELECT * FROM my_delta_table;

-- Update data
UPDATE my_delta_table SET name = 'Alice Smith' WHERE id = 1;

-- Merge data
MERGE INTO my_delta_table AS target
USING (SELECT 2 as id, 'Bob' as name, current_timestamp() as created_at) AS source
ON target.id = source.id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
```

**在 AWS Glue Data Catalog 中建立 Delta Lake 資料表**

Amazon EMR with Lake Formation 不支援在 7.12 之前的 EMR 版本中建立 DDL 命令和 Delta 資料表。請依照下列步驟，在 Glue Data Catalog AWS 中建立資料表。

1. 使用下列範例來建立 Delta 資料表。請確定您的 S3 位置存在。

   ```
   spark-sql \
   --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
   --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
   
   > CREATE DATABASE if not exists <DATABASE_NAME> LOCATION 's3://<S3_LOCATION>/transactionaldata/native-delta/<DATABASE_NAME>/';
   > CREATE TABLE <TABLE_NAME> (x INT, y STRING, z STRING) USING delta;
   > INSERT INTO <TABLE_NAME> VALUES (1, 'a1', 'b1');
   ```

1. 若要查看資料表的詳細資訊，請前往 https：//[https://console.aws.amazon.com/glue/](https://console.aws.amazon.com/glue/)。

1. 在左側導覽中，展開 **Data Catalog**，選擇**資料表**，然後選擇您建立的資料表。在**結構描述**下，您應該會看到您使用 Spark 建立的 Delta 資料表將所有資料欄存放在 Glue AWS 的資料類型`array<string>`中。

1. 若要在 Lake Formation 中定義資料欄和儲存格層級篩選條件，請從結構描述中移除資料`col`欄，然後新增資料表結構描述中的資料欄。在此範例中，新增欄 `x`、 `y`和 `z`。

------

此功能讓您能對寫入時複製資料表執行快照查詢，以查詢指定遞交或壓縮時的最新資料表快照。目前，已啟用 Lake Formation 的 Amazon EMR 叢集必須擷取 Hudi 的遞交時間欄，才能執行增量查詢和時間歷程查詢。它不支援 Spark `timestamp as of` 的語法和 `Spark.read()`函數。正確的語法為 `select * from table where _hoodie_commit_time <= point_in_time`。如需詳細資訊，請參閱 [Hudi 資料表上的時間歷程查詢](https://cwiki.apache.org/confluence/display/HUDI/RFC+-+07+%3A+Point+in+time+Time-Travel+queries+on+Hudi+table)。

**注意**  
由於不支援優化，Lake Formation 叢集上的讀取效能可能會變慢。這些功能包括基於 Hudi 中繼資料的檔案清單和資料略過。建議您測試應用程式效能，以確保符合您的要求。