

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon EMR でのマテリアライズドビューの使用
<a name="emr-spark-materialized-views"></a>

Amazon EMR リリース 7.12.0 AWS 以降では、 Glue データカタログでの Apache Iceberg マテリアライズドビューの作成と管理がサポートされています。マテリアライズドビューは、SQL クエリの事前計算された結果を Apache Iceberg 形式で保存し、基盤となるソーステーブルが変更されると段階的に更新するマネージドテーブルです。マテリアライズドビューを使用して、データ変換パイプラインを簡素化し、複雑な分析ワークロードのクエリパフォーマンスを高速化できます。

Amazon EMR で Spark を使用してマテリアライズドビューを作成すると、ビュー定義とメタデータが AWS Glue データカタログに保存されます。事前計算された結果は、 AWS アカウント内の Amazon S3 Tables バケットまたは Amazon S3 汎用バケットに Apache Iceberg テーブルとして保存されます。 AWS Glue Data Catalog は、ソーステーブルを自動的にモニタリングし、マネージドコンピューティングインフラストラクチャを使用してマテリアライズドビューを更新します。

**Topics**
+ [Amazon EMR でのマテリアライズドビューの仕組み](#emr-spark-materialized-views-how-it-works)
+ [前提条件](#emr-spark-materialized-views-prerequisites)
+ [マテリアライズドビューを使用するように Spark を設定する](#emr-spark-materialized-views-configure)
+ [マテリアライズドビューの作成](#emr-spark-materialized-views-create)
+ [マテリアライズドビューのクエリ](#emr-spark-materialized-views-query)
+ [「マテリアライズドビューの更新」](#emr-spark-materialized-views-refresh)
+ [マテリアライズドビューを管理する](#emr-spark-materialized-views-manage)
+ [マテリアライズドビューのアクセス許可](#emr-spark-materialized-views-permissions)
+ [マテリアライズドビューオペレーションをモニタリングする](#emr-spark-materialized-views-monitoring)
+ [例: ワークフローの完了](#emr-spark-materialized-views-example)
+ [考慮事項と制限事項](#emr-spark-materialized-views-limitations)

## Amazon EMR でのマテリアライズドビューの仕組み
<a name="emr-spark-materialized-views-how-it-works"></a>

マテリアライズドビューは、Apache Spark の Iceberg サポートを通じて Amazon EMR と統合されます。Glue データカタログを使用するように Spark AWS セッションを設定すると、標準の SQL 構文を使用してマテリアライズドビューを作成できます。Spark オプティマイザは、パフォーマンスを向上させるときにマテリアライズドビューを使用するようにクエリを自動的に書き換えることができるため、アプリケーションコードを手動で変更する必要はありません。

 AWS Glue データカタログは、以下を含むマテリアライズドビューメンテナンスのすべての運用面を処理します。
+ Apache Iceberg のメタデータレイヤーを使用したソーステーブルの変更の検出
+ マネージド Spark コンピューティングを使用した更新オペレーションのスケジュールと実行
+ データの変更に基づいて完全更新と増分更新のどちらを実行するかを決定する
+ 事前に計算された結果をマルチエンジンアクセス用に Apache Iceberg 形式で保存する

通常のテーブルに使用するのと同じ Spark SQL インターフェイスを使用して、Amazon EMR からマテリアライズドビューをクエリできます。事前に計算されたデータは、Amazon Athena や Amazon Redshift などの他のサービスからもアクセスできます。

## 前提条件
<a name="emr-spark-materialized-views-prerequisites"></a>

Amazon EMR でマテリアライズドビューを使用するには、以下が必要です。
+  AWS アカウント
+ リリース 7.12.0 以降を実行している Amazon EMR クラスター
+ Glue データカタログに登録された Apache Iceberg AWS 形式のソーステーブル
+ AWS ソーステーブルとターゲットデータベース用に設定された Lake Formation アクセス許可
+ マテリアライズドビューデータを保存するために Lake Formation に登録されている AWS S3 Tables バケットまたは S3 汎用バケット

## マテリアライズドビューを使用するように Spark を設定する
<a name="emr-spark-materialized-views-configure"></a>

マテリアライズドビューを作成および管理するには、必要な Iceberg 拡張機能とカタログ設定を使用して Spark セッションを設定します。設定は、ソーステーブルとマテリアライズドビューが S3 Tables バケットを使用するか、S3 汎用バケットを使用するかによって異なります。

### S3 テーブルの の設定
<a name="emr-spark-materialized-views-configure-s3-tables"></a>

マテリアライズドビューに S3 Tables バケットを使用する場合は、ソーステーブルとマテリアライズドビューに個別のカタログリファレンスを設定します。

```
spark-sql \
  --conf 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.type=glue \
  --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \
  --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \
  --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \
  --conf spark.sql.catalog.glue_catalog.glue.account-id=111122223333 \
  --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \
  --conf spark.sql.catalog.s3t_catalog=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.s3t_catalog.type=glue \
  --conf spark.sql.catalog.s3t_catalog.glue.id=111122223333:s3tablescatalog/my-table-bucket \
  --conf spark.sql.catalog.s3t_catalog.glue.account-id=111122223333 \
  --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \
  --conf spark.sql.catalog.s3t_catalog.warehouse=s3://amzn-s3-demo-bucket/mv-warehouse \
  --conf spark.sql.catalog.s3t_catalog.glue.region=us-east-1 \
  --conf spark.sql.defaultCatalog=s3t_catalog \
  // turn on automatic query rewrite (optional)
  --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true
```

### S3 汎用バケットの の設定
<a name="emr-spark-materialized-views-configure-s3-general"></a>

S3 汎用バケットを使用する場合は、単一のカタログリファレンスを設定します。

```
spark-sql \
  --conf 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.type=glue \
  --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \
  --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \
  --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \
  --conf spark.sql.catalog.s3t_catalog.glue.account-id=111122223333 \
  --conf spark.sql.catalog.s3t_catalog.glue.lakeformation-enabled=true \
  --conf spark.sql.defaultCatalog=glue_catalog \
  // turn on automatic query rewrite (optional)
  --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true
```

### 増分更新を有効化する
<a name="emr-spark-materialized-views-configure-incremental"></a>

増分更新の最適化を有効にするには、Spark セッションに次の設定プロパティを追加します。

```
spark-sql \
  --conf spark.sql.optimizer.incrementalMVRefresh.enabled=true \
```

### 設定パラメータ
<a name="emr-spark-materialized-views-configure-parameters"></a>

次の設定パラメータは、マテリアライズドビューの動作を制御します。
+ `spark.sql.extensions` – マテリアライズドビューのサポートに必要な Iceberg Spark セッション拡張機能を有効にします。
+ `spark.sql.optimizer.answerQueriesWithMVs.enabled` – マテリアライズドビューを使用するための自動クエリ書き換えを有効にします。この最適化をアクティブ化するには、true に設定します。
+ `spark.sql.optimizer.incrementalMVRefresh.enabled` – 増分更新の最適化を有効にします。更新オペレーション中に変更されたデータのみを処理するには、true に設定します。

## マテリアライズドビューの作成
<a name="emr-spark-materialized-views-create"></a>

CREATE MATERIALIZED VIEW SQL ステートメントを使用してマテリアライズドビューを作成します。ビュー定義は、変換ロジックを 1 つまたは複数のソーステーブルを参照する SQL クエリとして指定します。

### DLLs
<a name="emr-spark-materialized-views-create-dlls"></a>

**ビューの作成**

```
{ CREATE OR REPLACE MATERIALIZED VIEW | CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] }
   view_identifier
  [ view_clauses ]
  [ schedule_clauses ]
  AS [ select_statement ]

view_clauses =
  { [ LOCATION location ] |
    [ PARTITIONED BY (col [, ...]) ] |
    [ COMMENT view_comment ] |
    [ SCHEDULE [ REFRESH ] schedule_clause ] }

schedule_clause =
  { EVERY number { HOUR | HOURS | DAY | DAYS | WEEK | WEEKS } }
```

**注記**  
view\$1clauses は select\$1statement の前に表示する必要があります。

### 基本的なマテリアライズドビューの作成
<a name="emr-spark-materialized-views-create-basic"></a>

次の例では、顧客ごとに注文データを集約するマテリアライズドビューを作成し、ビュー定義で 3 つのパートの命名規則を持つ完全修飾テーブル名を使用します。

```
CREATE MATERIALIZED VIEW customer_orders
AS 
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM glue_catalog.sales.orders
GROUP BY customer_name;
```

### 自動更新でマテリアライズドビューを作成する
<a name="emr-spark-materialized-views-create-auto-refresh"></a>

自動更新を設定するには、ビュー定義で 3 つのパートの命名規則を持つ完全修飾テーブル名を使用してビューを作成するときに更新スケジュールを指定します。

```
CREATE MATERIALIZED VIEW customer_orders
SCHEDULE REFRESH EVERY 1 HOUR
AS 
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM glue_catalog.sales.orders
GROUP BY customer_name;
```

### クロスカタログ参照でマテリアライズドビューを作成する
<a name="emr-spark-materialized-views-create-cross-catalog"></a>

ソーステーブルがマテリアライズドビューとは異なるカタログにある場合は、ビュー名とビュー定義の両方に 3 つの部分で構成される命名規則を持つ完全修飾されたテーブル名を使用します。

```
CREATE MATERIALIZED VIEW s3t_catalog.analytics.customer_summary
AS 
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM glue_catalog.sales.orders
GROUP BY customer_name;
```

## マテリアライズドビューのクエリ
<a name="emr-spark-materialized-views-query"></a>

マテリアライズドビューを作成したら、標準の SQL SELECT ステートメントを使用して他のテーブルと同様にクエリを実行できます。

```
SELECT * FROM customer_orders;
```

### 自動クエリ書き換え
<a name="emr-spark-materialized-views-query-rewrite"></a>

自動クエリ書き換えを有効にすると、Spark オプティマイザはクエリを分析し、パフォーマンスを向上させることができるときにマテリアライズドビューを自動的に使用します。例えば、次のクエリを実行した場合を考えてみます。

```
SELECT 
    customer_name, 
    COUNT(*) as order_count, 
    SUM(amount) as total_amount 
FROM orders
GROUP BY customer_name;
```

マテリアライズドビューが最新である場合、Spark オプティマイザは、ベースの orders テーブルを処理する代わりに customer\$1orders マテリアライズドビューを使用するよう、このクエリを自動的に書き換えます。

### 自動クエリ書き換えを検証する
<a name="emr-spark-materialized-views-query-verify"></a>

クエリが自動クエリ書き換えを使用するかどうかを確認するには、EXPLAIN EXTENDED コマンドを使用します。

```
EXPLAIN EXTENDED
SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount 
FROM orders
GROUP BY customer_name;
```

実行プランで、BatchScan オペレーションでマテリアライズドビュー名を探します。BatchScan glue\$1catalog.sales.orders ではなく BatchScan glue\$1catalog.analytics.customer\$1orders がプランに表示される場合、マテリアライズドビューを使用するようにクエリが自動的に書き換えられています。

**注記**  
自動クエリ書き換えには、マテリアライズドビューの作成後に Spark メタデータキャッシュに入力する時間が必要です。通常、この処理は 30 秒以内に完了します。

## 「マテリアライズドビューの更新」
<a name="emr-spark-materialized-views-refresh"></a>

マテリアライズドビューは、2 つの方法 (フル更新または増分更新) で更新できます。フル更新では、すべてのベーステーブルデータからマテリアライズドビュー全体が再計算されますが、増分更新では、前回の更新以降に変更されたデータのみが処理されます。

### 手動完全更新
<a name="emr-spark-materialized-views-refresh-full"></a>

マテリアライズドビューの完全な更新を実行するには:

```
REFRESH MATERIALIZED VIEW customer_orders FULL;
```

このコマンドを実行したら、マテリアライズドビューをクエリして、更新された結果を確認します。

```
SELECT * FROM customer_orders;
```

### 手動増分更新
<a name="emr-spark-materialized-views-refresh-incremental"></a>

増分更新を実行するには、Spark セッション設定で増分更新が有効になっていることを確認して次を実行します。

```
REFRESH MATERIALIZED VIEW customer_orders;
```

 AWS Glue データカタログは、ビュー定義と変更されたデータの量に基づいて、増分更新が適用されるかどうかを自動的に判断します。増分更新が不可能な場合、オペレーションはフル更新に戻ります。

### 増分更新の実行を検証する
<a name="emr-spark-materialized-views-refresh-verify"></a>

増分更新が正常に実行されたことを確認するには、次のコマンドを実行して`lastRefreshType`テーブルのプロパティを確認できます。

```
SHOW TBLPROPERTIES <mvName>("lastRefreshType")
```

また、Spark ログ設定を変更してデバッグログを有効にすることでもこれを実現できます。

1. Spark log4j 設定ファイルを開きます。

   ```
   sudo vim /usr/lib/spark/conf/log4j2.properties
   ```

1. 次のロガー設定を追加します。

   ```
   logger.spark.name = org.apache.spark.sql
   logger.spark.level = debug
   
   logger.inmemcache.name = org.apache.spark.sql.InMemMvMetadataCache
   logger.inmemcache.level = off
   ```

1. 更新オペレーションを実行したら、Spark 出力で次のメッセージを検索します。

   ```
   DEBUG RefreshMaterializedViewExec: Executed Incremental Refresh
   ```

## マテリアライズドビューを管理する
<a name="emr-spark-materialized-views-manage"></a>

Amazon EMR には、マテリアライズドビューのライフサイクルを管理するための SQL コマンドが用意されています。

### マテリアライズドビューを説明する
<a name="emr-spark-materialized-views-manage-describe"></a>

マテリアライズドビューに関するメタデータ (定義、更新ステータス、最終更新タイムスタンプなど) を表示するには:

```
DESCRIBE EXTENDED customer_orders;
```

### マテリアライズドビューを変更する
<a name="emr-spark-materialized-views-manage-alter"></a>

既存のマテリアライズドビューの更新スケジュールを変更するには:

```
ALTER MATERIALIZED VIEW customer_orders 
ADD SCHEDULE REFRESH EVERY 2 HOURS;
```

自動更新を削除するには:

```
ALTER MATERIALIZED VIEW customer_orders 
DROP SCHEDULE;
```

### マテリアライズドビューを削除する
<a name="emr-spark-materialized-views-manage-drop"></a>

マテリアライズドビューを削除するには:

```
DROP MATERIALIZED VIEW customer_orders;
```

このコマンドは、 AWS Glue データカタログからマテリアライズドビュー定義を削除し、基盤となる Iceberg テーブルデータを S3 バケットから削除します。

## マテリアライズドビューのアクセス許可
<a name="emr-spark-materialized-views-permissions"></a>

マテリアライズドビューを作成および管理するには、 AWS Lake Formation アクセス許可を設定する必要があります。マテリアライズドビューを作成する IAM ロール (定義ロール) には、ソーステーブルとターゲットデータベースに対する特定のアクセス許可が必要です。

### 定義者ロールに必要なアクセス許可
<a name="emr-spark-materialized-views-permissions-definer"></a>

定義者ロールには、次の Lake Formation アクセス許可が必要です。
+ ソーステーブル – 行、列、またはセルフィルターが適用されていない SELECT または ALL アクセス許可
+ ターゲットデータベース – CREATE\$1TABLE アクセス許可
+ Glue データカタログ AWS – GetTable および CreateTable API アクセス許可

マテリアライズドビューを作成すると、定義ロールの ARN がビュー定義に保存されます。 AWS Glue データカタログは、自動更新オペレーションを実行するときにこのロールを引き受けます。定義者ロールがソーステーブルへのアクセスを失った場合、アクセス許可が復元されるまで更新オペレーションは失敗します。

### マテリアライズドビューへのアクセスを付与する
<a name="emr-spark-materialized-views-permissions-access"></a>

他のユーザーにマテリアライズドビューをクエリするためのアクセス許可を付与するには、 AWS Lake Formation を使用してマテリアライズドビューテーブルに対する SELECT アクセス許可を付与します。ユーザーは、マテリアライズドビューをクエリできます。基盤となるソーステーブルに直接アクセスする必要はありません。

Lake Formation アクセス許可の設定の詳細については、 AWS Lake Formation デベロッパーガイドの「データカタログリソースに対するアクセス許可の付与と取り消し」を参照してください。

## マテリアライズドビューオペレーションをモニタリングする
<a name="emr-spark-materialized-views-monitoring"></a>

 AWS Glue データカタログは、マテリアライズドビューの更新オペレーションのメトリクスとログを Amazon CloudWatch に発行します。更新ステータス、期間、処理されたデータボリュームを CloudWatch メトリクスからモニタリングできます。

### 更新メトリクスの表示
<a name="emr-spark-materialized-views-monitoring-metrics"></a>

マテリアライズドビューの更新メトリクスを表示するには:

1. CloudWatch コンソールを開きます。

1. ナビゲーションペインからメトリクスを選択します。

1. [Glue] 名前空間を選択します。

1. マテリアライズドビュー名でメトリクスをフィルタリングします。

### アラームを設定する
<a name="emr-spark-materialized-views-monitoring-alarms"></a>

更新オペレーションが失敗したとき、または想定期間を超えたときに通知を受け取るには、マテリアライズドビューメトリクスで CloudWatch アラームを作成します。Amazon EventBridge ルールを設定して、更新イベントへの自動応答をトリガーすることもできます。

## 例: ワークフローの完了
<a name="emr-spark-materialized-views-example"></a>

次の例は、Amazon EMR でマテリアライズドビューを作成して使用する完全なワークフローを示しています。

1. SSH を使用して EMR クラスターのプライマリノードに接続します。

1. サンプルデータを含むベーステーブルを作成します。

   ```
   spark-sql \
     --conf 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.type=glue \
     --conf spark.sql.catalog.glue_catalog.warehouse=s3://amzn-s3-demo-bucket/warehouse \
     --conf spark.sql.catalog.glue_catalog.glue.region=us-east-1 \
     --conf spark.sql.catalog.glue_catalog.glue.id=111122223333 \
     --conf spark.sql.catalog.glue_catalog.glue.account-id=111122223333 \
     --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true \
     --conf spark.sql.defaultCatalog=glue_catalog \
     --conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true 
   
   
   CREATE DATABASE IF NOT EXISTS sales;
   
   USE sales;
   
   CREATE TABLE orders (
       id INT,
       customer_name STRING,
       amount DECIMAL(10,2),
       order_date DATE
   );
   
   INSERT INTO orders VALUES 
       (1, 'John Doe', 150.00, DATE('2024-01-15')),
       (2, 'Jane Smith', 200.50, DATE('2024-01-16')),
       (3, 'Bob Johnson', 75.25, DATE('2024-01-17'));
   ```

1. マテリアライズドビューを作成します。

   ```
   CREATE MATERIALIZED VIEW customer_summary
   AS 
   SELECT 
       customer_name, 
       COUNT(*) as order_count, 
       SUM(amount) as total_amount 
   FROM glue_catalog.sales.orders
   GROUP BY customer_name;
   ```

1. マテリアライズドビューをクエリします。

   ```
   SELECT * FROM customer_summary;
   ```

1. ベーステーブルに追加データを挿入します。

   ```
   INSERT INTO orders VALUES 
       (4, 'Jane Smith', 350.00, DATE('2024-01-18')),
       (5, 'Bob Johnson', 100.25, DATE('2024-01-19'));
   ```

1. マテリアライズドビューを更新します。

   ```
   REFRESH MATERIALIZED VIEW customer_summary FULL;
   ```

1. 更新された結果を確認します。

   ```
   SELECT * FROM customer_summary;
   ```

## 考慮事項と制限事項
<a name="emr-spark-materialized-views-limitations"></a>

Amazon EMR でマテリアライズドビューを使用する場合は、次の点を考慮してください。
+ マテリアライズドビューには、Amazon EMR リリース 7.12.0 以降が必要です。
+ ソーステーブルは、 Glue データカタログに登録されている Apache Iceberg AWS テーブルである必要があります。ローンチの時点では、Apache Hive、Apache Hudi、Linux Foundation Delta Lake テーブルはサポートされていません。
+ ソーステーブルは、マテリアライズドビューと同じ AWS リージョンと AWS アカウントに存在する必要があります。
+ すべてのソーステーブルは AWS Lake Formation によって管理される必要があります。IAM のみのアクセス許可とハイブリッドアクセスはサポートされていません。
+ マテリアライズドビューは AWS 、 Glue データカタログビュー、マルチダイアレクトビュー、またはその他のマテリアライズドビューをソーステーブルとして参照することはできません。
+ ビュー定義ロールには、行、列、またはセルフィルターが適用されていないすべてのソーステーブルに対するフル読み取りアクセス (SELECT または ALL アクセス許可) が必要です。
+ マテリアライズドビューは、結果的にソーステーブルと整合します。更新中に、クエリが古いデータを返すことがあります。即自的な整合性が必要な場合は手動更新を実行します。
+ 自動更新の最小間隔は 1 時間です。
+ 増分更新は、SQL オペレーションの制限されたサブセットをサポートします。ビュー定義は単一の SELECT-FROM-WHERE-GROUP BY-HAVING ブロックである必要があり、セットオペレーション、サブクエリ、SELECT または集計関数の DISTINCT キーワード、ウィンドウ関数、INNER JOIN 以外の結合を含むことはできません。
+ 増分更新は、ユーザー定義関数と特定の組み込み関数をサポートしていません。Spark SQL 組み込み関数のサブセットのみがサポートされています。
+ クエリの自動書き換えでは、増分更新の制限と同様に、制限された SQL サブセットに定義が属するマテリアライズドビューのみが考慮されます。
+ フル更新オペレーションはテーブル全体を上書きし、以前のスナップショットが使用できなくなります。
+ 英数字とアンダースコア以外の特殊文字を含む識別子は、CREATE MATERIALIZED VIEW クエリでサポートされません。
+ \$1\$1ivm プレフィックスで始まるマテリアライズドビュー列は、システム用に予約されています。 は、将来のリリースでこれらの列を変更または削除する権利 AWS を予約します。
+ SORT BY、LIMIT、OFFSET、CLUSTER BY、ORDER BY の句は、マテリアライズドビュー定義ではサポートされません。
+ クロスリージョンソーステーブルとクロスアカウントソーステーブルはサポートされません。
+ rand() や current\$1timestamp() などの非決定論的関数は、マテリアライズドビュー定義でサポートされません。