

# AWS Glue でマテリアライズドビューを使用する
<a name="materialized-views"></a>

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

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

**Topics**
+ [マテリアライズドビューと AWS Glue が連動する仕組み](#materialized-views-how-they-work)
+ [前提条件](#materialized-views-prerequisites)
+ [マテリアライズドビューを使用するように Spark を設定する](#materialized-views-configuring-spark)
+ [マテリアライズドビューの作成](#materialized-views-creating)
+ [マテリアライズドビューのクエリ](#materialized-views-querying)
+ [「マテリアライズドビューの更新」](#materialized-views-refreshing)
+ [マテリアライズドビューを管理する](#materialized-views-managing)
+ [マテリアライズドビューのアクセス許可](#materialized-views-permissions)
+ [マテリアライズドビューオペレーションをモニタリングする](#materialized-views-monitoring)
+ [例: ワークフローの完了](#materialized-views-complete-workflow)
+ [考慮事項と制限事項](#materialized-views-considerations-limitations)

## マテリアライズドビューと AWS Glue が連動する仕組み
<a name="materialized-views-how-they-work"></a>

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

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

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

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

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

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

AWS Glue でマテリアライズドビューを作成および管理するには、必要な Iceberg 拡張機能とカタログ設定をで Spark セッションを設定します。設定方法は、AWS Glue ジョブと AWS Glue Studio ノートブックのどちらを使用しているかに応じて異なります。

### AWS Glue ジョブを設定する
<a name="materialized-views-configuring-glue-jobs"></a>

AWS Glue ジョブを作成または更新するときは、次の設定パラメータをジョブパラメータとして追加します。

#### S3 Tables バケットの場合
<a name="materialized-views-s3-tables-buckets"></a>

```
job = glue.create_job(
    Name='materialized-view-job',
    Role='arn:aws:iam::111122223333:role/GlueServiceRole',
    Command={
        'Name': 'glueetl',
        'ScriptLocation': 's3://amzn-s3-demo-bucket/scripts/mv-script.py',
        'PythonVersion': '3'
    },
    DefaultArguments={
        '--enable-glue-datacatalog': 'true',
        '--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 '
                  '--conf spark.sql.optimizer.answerQueriesWithMVs.enabled=true '
                  '--conf spark.sql.materializedViews.metadataCache.enabled=true'
    },
    GlueVersion='5.1'
)
```

#### S3 汎用バケットの場合
<a name="materialized-views-s3-general-purpose-buckets"></a>

```
job = glue.create_job(
    Name='materialized-view-job',
    Role='arn:aws:iam::111122223333:role/GlueServiceRole',
    Command={
        'Name': 'glueetl',
        'ScriptLocation': 's3://amzn-s3-demo-bucket/scripts/mv-script.py',
        'PythonVersion': '3'
    },
    DefaultArguments={
        '--enable-glue-datacatalog': 'true',
        '--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 '
                  '--conf spark.sql.materializedViews.metadataCache.enabled=true'
    },
    GlueVersion='5.1'
)
```

### AWS Glue Studio ノートブックを設定する
<a name="materialized-views-configuring-glue-studio-notebooks"></a>

AWS Glue Studio ノートブックで、ノートブックの先頭で %%configure マジックコマンドを使用して Spark セッションを設定します。

```
%%configure
{
    "conf": {
        "spark.sql.extensions": "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions",
        "spark.sql.catalog.glue_catalog": "org.apache.iceberg.spark.SparkCatalog",
        "spark.sql.catalog.glue_catalog.type": "glue",
        "spark.sql.catalog.glue_catalog.warehouse": "s3://amzn-s3-demo-bucket/warehouse",
        "spark.sql.catalog.glue_catalog.glue.region": "us-east-1",
        "spark.sql.catalog.glue_catalog.glue.id": "111122223333",
        "spark.sql.catalog.glue_catalog.glue.account-id": "111122223333",
        "spark.sql.catalog.glue_catalog.glue.lakeformation-enabled": "true",
        "spark.sql.defaultCatalog": "glue_catalog",
        "spark.sql.optimizer.answerQueriesWithMVs.enabled": "true",
        "spark.sql.materializedViews.metadataCache.enabled": "true"
    }
}
```

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

増分更新の最適化を有効にするには、ジョブパラメータまたはノートブック設定に次の設定プロパティを追加します。

```
--conf spark.sql.optimizer.incrementalMVRefresh.enabled=true
--conf spark.sql.optimizer.incrementalMVRefresh.deltaThresholdCheckEnabled=false
```

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

次の設定パラメータは、マテリアライズドビューの動作を制御します。
+ `spark.sql.extensions` – マテリアライズドビューのサポートに必要な Iceberg Spark セッション拡張機能を有効にします。
+ `spark.sql.optimizer.answerQueriesWithMVs.enabled` – マテリアライズドビューを使用するための自動クエリ書き換えを有効にします。この最適化をアクティブ化するには、true に設定します。
+ `spark.sql.materializedViews.metadataCache.enabled` – クエリ最適化のためのマテリアライズドビューメタデータのキャッシュを有効にします。クエリの書き換えパフォーマンスを向上させるには、true に設定します。
+ `spark.sql.optimizer.incrementalMVRefresh.enabled` – 増分更新の最適化を有効にします。更新オペレーション中に変更されたデータのみを処理するには、true に設定します。
+ `spark.sql.optimizer.answerQueriesWithMVs.decimalAggregateCheckEnabled` – クエリの書き換えにおける 10 進集計オペレーションの検証を制御します。false に設定すると、特定の 10 進オーバーフローチェックが無効になります。

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

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

### AWS Glue ジョブで基本的なマテリアライズドビューを作成する
<a name="materialized-views-creating-basic-glue-jobs"></a>

次の例は、AWS Glue ジョブスクリプトでマテリアライズドビューを作成し、ビュー定義で 3 つの部分で構成される命名規則を持つ完全修飾されたテーブル名を使用する方法を示しています。

```
from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

# Create materialized view
spark.sql("""
    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="materialized-views-creating-automatic-refresh"></a>

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

```
spark.sql("""
    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="materialized-views-creating-cross-catalog"></a>

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

```
spark.sql("""
    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
""")
```

### AWS Glue Studio ノートブックにマテリアライズドビューを作成する
<a name="materialized-views-creating-glue-studio-notebooks"></a>

AWS Glue Studio ノートブックでは、ビュー定義で 3 つの部分から構成される命名規則を持つ完全修飾されたテーブル名を使用して、%%sql マジックコマンドでマテリアライズドビューを作成できます。

```
%%sql
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="materialized-views-querying"></a>

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

### AWS Glue ジョブでクエリする
<a name="materialized-views-querying-glue-jobs"></a>

```
from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

# Query materialized view
result = spark.sql("SELECT * FROM customer_orders")
result.show()
```

### AWS Glue Studio ノートブックでクエリする
<a name="materialized-views-querying-glue-studio-notebooks"></a>

```
%%sql
SELECT * FROM customer_orders
```

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

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

```
result = spark.sql("""
    SELECT 
        customer_name, 
        COUNT(*) as order_count, 
        SUM(amount) as total_amount 
    FROM orders
    GROUP BY customer_name
""")
```

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

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

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

```
spark.sql("""
    EXPLAIN EXTENDED
    SELECT customer_name, COUNT(*) as order_count, SUM(amount) as total_amount 
    FROM orders
    GROUP BY customer_name
""").show(truncate=False)
```

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

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

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

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

### AWS Glue ジョブの手動フル更新
<a name="materialized-views-manual-full-refresh-glue-jobs"></a>

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

```
spark.sql("REFRESH MATERIALIZED VIEW customer_orders FULL")

# Verify updated results
result = spark.sql("SELECT * FROM customer_orders")
result.show()
```

### AWS Glue ジョブの手動増分更新
<a name="materialized-views-manual-incremental-refresh-glue-jobs"></a>

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

```
spark.sql("REFRESH MATERIALIZED VIEW customer_orders")

# Verify updated results
result = spark.sql("SELECT * FROM customer_orders")
result.show()
```

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

### AWS Glue Studio ノートブックで更新する
<a name="materialized-views-refreshing-glue-studio-notebooks"></a>

ノートブックで、%%sql マジックコマンドを使用します。

```
%%sql
REFRESH MATERIALIZED VIEW customer_orders FULL
```

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

増分更新が正常に実行されたことを確認するには、AWS Glue ジョブでデバッグログ記録を有効にします。

```
from awsglue.context import GlueContext
from pyspark.context import SparkContext
import logging

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

# Enable debug logging
logger = logging.getLogger('org.apache.spark.sql')
logger.setLevel(logging.DEBUG)

# Execute refresh
spark.sql("REFRESH MATERIALIZED VIEW customer_orders")
```

AWS Glue ジョブログで次のメッセージを探します。

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

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

AWS Glue には、ジョブとノートブックのマテリアライズドビューのライフサイクルを管理するための SQL コマンドが用意されています。

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

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

```
spark.sql("DESCRIBE EXTENDED customer_orders").show(truncate=False)
```

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

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

```
spark.sql("""
    ALTER MATERIALIZED VIEW customer_orders 
    ADD SCHEDULE REFRESH EVERY 2 HOURS
""")
```

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

```
spark.sql("""
    ALTER MATERIALIZED VIEW customer_orders 
    DROP SCHEDULE
""")
```

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

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

```
spark.sql("DROP MATERIALIZED VIEW customer_orders")
```

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

### マテリアライズドビューを一覧表示する
<a name="materialized-views-listing"></a>

データベース内のすべてのマテリアライズドビューを一覧表示するには:

```
spark.sql("SHOW VIEWS FROM analytics").show()
```

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

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

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

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

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

### AWS Glue ジョブの IAM アクセス許可
<a name="materialized-views-iam-permissions-glue-jobs"></a>

AWS Glue ジョブの IAM ロールには、次のアクセス許可が必要です。

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "glue:GetCatalog",
                "glue:GetCatalogs",
                "glue:GetTable",
                "glue:GetTables",
                "glue:CreateTable",
                "glue:UpdateTable",
                "glue:DeleteTable",
                "glue:GetDatabase",
                "glue:GetDatabases",
                "cloudwatch:PutMetricData"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::amzn-s3-demo-bucket/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::amzn-s3-demo-bucket"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*:/aws-glue/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "lakeformation:GetDataAccess"
            ],
            "Resource": "*"
        }
    ]
}
```

マテリアライズドビューの自動更新に使用するロールには、ロールに対する iam:PassRole アクセス許可が必要です。

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:PassRole"
      ],
      "Resource": [
        "arn:aws:iam::111122223333:role/materialized-view-role-name"
      ]
    }
  ]
}
```

Glue でマテリアライズドビューを自動的に更新するには、サービスがロールを引き受けることができる次の信頼ポリシーもロールに必要です。

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:PassRole"
      ],
      "Resource": [
        "arn:aws:iam::111122223333:role/materialized-view-role-name"
      ]
    }
  ]
}
```

マテリアライズドビューが S3 Tables バケットに保存されている場合は、ロールに次のアクセス許可も追加する必要があります。

```
{
  "Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3tables:PutTableMaintenanceConfiguration"
      ],
      "Resource": "arn:aws:s3tables:*:123456789012:*"
    }
  ]
}
```

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

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

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

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

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

### ジョブログを表示する
<a name="materialized-views-viewing-job-logs"></a>

マテリアライズドビューを作成または更新する AWS Glue ジョブのログを表示するには:

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

1. ナビゲーションペインで、[Jobs] を選択します。

1. 目的のジョブを選択し、[Runs] を選択します。

1. 特定の実行を選択し、[Logs] を選択して CloudWatch ログを表示します。

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

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

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

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

### AWS Glue ジョブスクリプトの例
<a name="materialized-views-example-glue-job-script"></a>

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# Create database and base table
spark.sql("CREATE DATABASE IF NOT EXISTS sales")
spark.sql("USE sales")

spark.sql("""
    CREATE TABLE IF NOT EXISTS orders (
        id INT,
        customer_name STRING,
        amount DECIMAL(10,2),
        order_date DATE
    )
""")

# Insert sample data
spark.sql("""
    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'))
""")

# Create materialized view
spark.sql("""
    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
""")

# Query the materialized view
print("Initial materialized view data:")
spark.sql("SELECT * FROM customer_summary").show()

# Insert additional data
spark.sql("""
    INSERT INTO orders VALUES 
        (4, 'Jane Smith', 350.00, DATE('2024-01-18')),
        (5, 'Bob Johnson', 100.25, DATE('2024-01-19'))
""")

# Refresh the materialized view
spark.sql("REFRESH MATERIALIZED VIEW customer_summary FULL")

# Query updated results
print("Updated materialized view data:")
spark.sql("SELECT * FROM customer_summary").show()

job.commit()
```

### AWS Glue Studio ノートブックの例
<a name="materialized-views-example-glue-studio-notebook"></a>

```
%%configure
{
    "conf": {
        "spark.sql.extensions": "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions",
        "spark.sql.catalog.glue_catalog": "org.apache.iceberg.spark.SparkCatalog",
        "spark.sql.catalog.glue_catalog.type": "glue",
        "spark.sql.catalog.glue_catalog.warehouse": "s3://amzn-s3-demo-bucket/warehouse",
        "spark.sql.catalog.glue_catalog.glue.region": "us-east-1",
        "spark.sql.catalog.glue_catalog.glue.id": "111122223333",
        "spark.sql.catalog.glue_catalog.glue.account-id": "111122223333",
        "spark.sql.catalog.glue_catalog.glue.lakeformation-enabled": "true",
        "spark.sql.defaultCatalog": "glue_catalog",
        "spark.sql.optimizer.answerQueriesWithMVs.enabled": "true",
        "spark.sql.materializedViews.metadataCache.enabled": "true"
    }
}
```

```
%%sql
CREATE DATABASE IF NOT EXISTS sales
```

```
%%sql
USE sales
```

```
%%sql
CREATE TABLE IF NOT EXISTS orders (
    id INT,
    customer_name STRING,
    amount DECIMAL(10,2),
    order_date DATE
)
```

```
%%sql
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'))
```

```
%%sql
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
```

```
%%sql
SELECT * FROM customer_summary
```

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

```
%%sql
REFRESH MATERIALIZED VIEW customer_summary FULL
```

```
%%sql
SELECT * FROM customer_summary
```

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

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