Snowflake Catalog における Iceberg テーブルの基本的な操作手順



# 概要

本記事では、**Snowflake Catalog** の全体像を理解するための学習コンテンツを紹介します。Snowflake Catalog を実際に検証する際には外部サービスとの連携が必要ですが、ここでは主に **Google Colab** 上で **Spark** を利用した操作手順を中心に解説します。本記事を通じて、Snowflake Catalog についての理解が深まれば幸いです。

- 環境構築
    - Azure Stroage 環境の構築
    - Snowflake 環境での事前準備
    - 外部ボリュームの作成
- Snowflake 上での Snowflake-managed Iceberg テーブルの操作
    - テーブル作成
    - データロード
    - クエリの実行
- Snowflake Catalog SDK による Spark からの接続
- Open Catalog への同期
    - Snowflake Open Catalog 環境の準備
    - 既存の Iceberg テーブルを Snowflake Open Catalog に同期
    - テーブル作成時に Snowflake Open Catalog へ同期

Snowflake Open Catalog での学習コンテンツについては、以下の記事をご参照ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/64c3c19e-d28b-4d18-8835-7b2413e34559.png)

出所：[Snowflake Open Catalog における Iceberg テーブルの基本的な操作手順 #Spark - Qiita](https://qiita.com/manabian/items/0965d17596da6883e686)


## Snowflake Catalog について

**Snowflake Catalog** は、Snowflake が内部で提供する **Apache Iceberg™ REST プロトコル** による Apache Iceberg のテーブルカタログ機能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/aa4c1327-93d6-4c1f-9c76-133dd4905c1b.png)

出所：[Apache Iceberg™ テーブル | Snowflake Documentation](https://docs.snowflake.com/ja/user-guide/tables-iceberg)

Snowflake 上で Apache Iceberg を利用する方法としては、以下の 2 つがあります。

1. Snowflake をカタログとして利用（Snowflake Catalog）
2. Snowflake Open Catalog（マネージド Apache Polaris）を利用

本記事は主に前者の **Snowflake Catalog** に関する手順を解説します。なお、Snowflake Catalog 上で管理しているテーブルを **Snowflake Open Catalog** に同期させることも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/998c7cc8-74d7-4f8c-a9ed-ab92dd5cfcad.png)

出所：[Snowflakeオープンカタログをはじめるにあたり | Snowflake Documentation](https://other-docs.snowflake.com/ja/opencatalog/tutorials/open-catalog-gs)

本記事の内容は Snowflake の公式チュートリアルをベースにしています。下記の公式チュートリアルも併せてご確認ください。

- [チュートリアル: Apache Iceberg™ テーブルを作成する | Snowflake Documentation](https://docs.snowflake.com/ja/user-guide/tutorials/create-your-first-iceberg-table#introduction)

また、Google Colab 上で Spark を操作するための基本的な手順は、以下の記事をご参照ください。

- [Google Colab 上で Spark を利用する方法 #Python - Qiita](https://qiita.com/manabian/items/7beb6ae0fedf34c2291e)

## 環境構築

### Azure Storage 環境の構築

まず、Azure Storage アカウントを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d0405887-f450-4615-826b-3475412b45dd.png)

`snowflake` という名前のコンテナーを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/aaed88c2-f943-4bc0-8372-4cd5db9b91fe.png)

`snowflakecatalog` というディレクトリを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/15fe4ea3-d228-4cbc-b3ba-df6b80e0b3ea.png)

### 検証用のデータベースを作成

```sql
CREATE OR REPLACE DATABASE SNOWFLAKE_CATALOG_TUTORIAL_DB;
USE DATABASE SNOWFLAKE_CATALOG_TUTORIAL_DB;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/31e4c18a-80c9-4bf3-836b-3e3e20040304.png)

### 外部 Volume を作成

`CREATE EXTERNAL VOLUME` 文は変数を直接使用できないため、設定値を生成してコピー＆ペーストします。まずは必要な値を変数に格納します。

```sql
-- 各値を変数としてセット
SET azure_tenant_id = '095ca098-c723-478f-xxxx-xxxxx';
SET azure_storage_account_name = 'snowflakeicebergqiita';
SET storage_provider = 'AZURE';

-- 連結した URL は変数に事前に設定
SET full_storage_uri = 'azure://' || $azure_storage_account_name || '.blob.core.windows.net/snowflake/snowflakecatalog/';


SELECT
    $storage_provider AS  STORAGE_PROVIDER
    ,$full_storage_uri AS STORAGE_BASE_URL
    ,$azure_tenant_id AS AZURE_TENANT_ID;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/155b2625-0dad-4b00-8233-cd30dc6ef0bd.png)

上記のクエリで取得した値を参考に、下記の `CREATE EXTERNAL VOLUME` 文をコピー＆ペーストして実行します。

```sql
-- 外部 Volume を作成
CREATE OR REPLACE EXTERNAL VOLUME my_azure_sf_volume
    STORAGE_LOCATIONS = (
        (
          NAME = 'my-azure-sf-container'
          STORAGE_PROVIDER = 'AZURE'
          STORAGE_BASE_URL = 'azure://snowflakeicebergqiita.blob.core.windows.net/snowflake/snowflakecatalog/'
          AZURE_TENANT_ID = '095ca098-c723-478f-xxxx-xxxxx'
        )
    )
    ALLOW_WRITES = true;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6c7d9cd9-b90c-44e5-98f2-3f057ae185df.png)

作成した Volume を確認します。

```sql
DESC EXTERNAL VOLUME my_azure_sf_volume;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e354f62a-b4ca-4f4d-8115-210dd9b00bc1.png)

### 外部 Volume に対する権限の付与

次に、`AZURE_CONSENT_URL` の URL を Azure にログインしているブラウザで開き、Snowflake からのアクセス許可を付与します。

```sql
DESC EXTERNAL VOLUME my_azure_sf_volume;
SELECT 
    PARSE_JSON($4):AZURE_MULTI_TENANT_APP_NAME::string AS AZURE_MULTI_TENANT_APP_NAME,
    PARSE_JSON($4):AZURE_CONSENT_URL::string AS AZURE_CONSENT_URL
FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
WHERE $2 = 'STORAGE_LOCATION_1';
```

`承諾` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0ac04b60-8a5b-47c8-b66c-a3a24be08125.png)

Azure Storage 側で `AZURE_MULTI_TENANT_APP_NAME` のアンダーバーより前のアプリケーション（例：`ps27tlsnowflakepacint`）を検索し、適切なロールを付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d31403fe-9c9d-4067-81cd-887d17b1dacb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4f6f351c-726f-43e9-a4e7-0a34b31dcc2a.png)

:::note info
本記事は Azure 環境向けの手順を示していますが、Snowflake のドキュメントにはクラウドベンダー別の手順が用意されています。

- [Amazon S3用の外部ボリュームを構成する | Snowflake Documentation](https://docs.snowflake.com/ja/user-guide/tables-iceberg-configure-external-volume-s3)
- [Google Cloud Storageの外部ボリュームを構成する | Snowflake Documentation](https://docs.snowflake.com/ja/user-guide/tables-iceberg-configure-external-volume-gcs)
- [Azureの外部ボリュームを構成する | Snowflake Documentation](https://docs.snowflake.com/ja/user-guide/tables-iceberg-configure-external-volume-azure)
:::

## Snowflake 上での Snowflake-managed Iceberg テーブル操作

### テーブル作成

```sql
CREATE OR REPLACE ICEBERG TABLE customer_iceberg (
    c_custkey INTEGER,
    c_name STRING,
    c_address STRING,
    c_nationkey INTEGER,
    c_phone STRING,
    c_acctbal INTEGER,
    c_mktsegment STRING,
    c_comment STRING
)
    CATALOG = 'SNOWFLAKE'
    EXTERNAL_VOLUME = 'my_azure_sf_volume'
    BASE_LOCATION = 'customer_iceberg';
```

```sql
SHOW TABLES IN DATABASE SNOWFLAKE_CATALOG_TUTORIAL_DB
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/adff7213-ca7f-4c1a-9a68-8a723c35d651.png)

以下のように `metadata file` を確認し、`00000` になっていることを確認します。

```sql
SELECT SYSTEM$GET_ICEBERG_TABLE_INFORMATION('CUSTOMER_ICEBERG');
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/30327718-a316-4dde-a03c-e2ff7c6baa0e.png)

### データロード

```sql
INSERT INTO customer_iceberg
  SELECT * FROM snowflake_sample_data.tpch_sf1.customer;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/df7c97c5-d98a-4523-bbef-91bcf8605c23.png)

再度 `metadata file` を確認すると、`00001` に更新されています。

```sql
SELECT SYSTEM$GET_ICEBERG_TABLE_INFORMATION('CUSTOMER_ICEBERG');
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f54f564d-1960-4205-8fc0-c69055ce299f.png)

### クエリの実行

```sql
SELECT
    *
    FROM
        customer_iceberg
    LIMIT 10;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/28fc175f-c3b0-4f5b-81fc-7b48d45be092.png)

### DELETE の実施

```sql
DELETE FROM CUSTOMER_ICEBERG
    WHERE c_mktsegment = 'AUTOMOBILE';
```

```sql
SELECT * FROM CUSTOMER_ICEBERG WHERE c_mktsegment = 'AUTOMOBILE';
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a377e03f-753e-4aea-9b7d-602647c51c40.png)

再度 `metadata file` を確認すると、`00002` に更新されています。

```sql
SELECT SYSTEM$GET_ICEBERG_TABLE_INFORMATION('CUSTOMER_ICEBERG');
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1f4455b9-8234-4139-b7ff-b1855c9e5aea.png)

## Snowflake Catalog SDK により Spark から接続

### Azure Storage で `アクセスキー` タブにある `key1` の値を取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/69485420-e8e3-403c-9d56-ff8753dbc9d6.png)

### Google Colab のノートブックを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1353a0fe-d21f-467b-808e-2bdd529a4977.png)

### Spark のバージョンを確認

```bash
!pyspark --version
```

### Snowflake の account_identifier と認証情報を変数にセット

```py
# Snowflake 
account_identifier = "MTIRXWM-ZJA50722"
user_name = "MANABIAN"
password = "3-g!qNmm9uXXXXX"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/df0e229d-b113-4927-97df-389157c2b726.png)

### Azure Storage の名称とキーを変数にセット

```py
# Azure Storage に関する情報をセット
azure_storage_account_name = "snowflakeicebergqiita"
azure_storage_account_key = "cBGfLSEInUgJ+e6w/bx7x4yewwOqDIIGE7sjPUMttki9CzXXXXXXXX=="
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c40e4932-c64a-4a8d-bc79-52bd2bb9332f.png)

### SparkSession の定義と疎通確認

```python

from pyspark.sql import SparkSession

spark = (
    SparkSession.builder.appName("iceberg_lab")
    .config(
        "spark.jars.packages",
        "org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.8.1,"
        "net.snowflake:snowflake-jdbc:3.23.0,"
        "org.apache.hadoop:hadoop-azure:3.2.0"
    )
    .config("spark.sql.defaultCatalog", "snowflake_catalog")
    .config("spark.sql.catalog.snowflake_catalog", "org.apache.iceberg.spark.SparkCatalog")
    .config("spark.sql.catalog.snowflake_catalog.catalog-impl", "org.apache.iceberg.snowflake.SnowflakeCatalog")
    .config("spark.sql.catalog.snowflake_catalog.uri", f"jdbc:snowflake://{account_identifier}.snowflakecomputing.com")
    .config("spark.sql.catalog.snowflake_catalog.jdbc.user", user_name)
    .config("spark.sql.catalog.snowflake_catalog.jdbc.password", password)
    .config("spark.sql.catalog.snowflake_catalog.io-impl", "org.apache.iceberg.hadoop.HadoopFileIO")
    .config(f"spark.hadoop.fs.azure.account.key.{azure_storage_account_name}.blob.core.windows.net", azure_storage_account_key)
    .getOrCreate()
)
spark
````

```python
spark.sql("SHOW NAMESPACES").show(truncate=False)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d67231c8-4c91-4a4f-8653-a95cbb1aaa23.png)

### テーブルのデータを取得

```python
df = (
    spark.read
        .format("iceberg")
        .option("vectorization-enabled", "false")
        .table("SNOWFLAKE_CATALOG_TUTORIAL_DB.PUBLIC.CUSTOMER_ICEBERG")
)
df.limit(10).show(truncate=False)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/996bba86-725d-409f-a14a-43cd631f4a0f.png)

## Snowflake Open Catalog への自動同期

### Snowflake Open Catalog 環境の準備

#### Snowflake Open Catalog のアカウントを作成

まず、`ORGADMIN` ロールに切り替えます。

```sql
-- ORGADMIN にカレントロールを変更
USE ROLE ORGADMIN;
SELECT CURRENT_ROLE();
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1c89c218-219d-49a2-b4a7-036c55dee1bc.png)

次に、Snowflake Open Catalog が有効なアカウントを新規作成します。

```sql
-- Snowflake Open Catalog が有効な Snowflake アカウントを作成
-- ToDo EMAIL と REGION を変更する必要あり
CREATE ACCOUNT manabian_opencatalog_00_account
   ADMIN_NAME = 'opencatalog_admin'
   ADMIN_PASSWORD = 'MySecurePassword2025!'
   EMAIL = 'admin@example.com'
   MUST_CHANGE_PASSWORD = FALSE
   EDITION = ENTERPRISE
   REGION = 'AZURE_EASTUS2'
   POLARIS = TRUE;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/06eac16e-c5e3-4bdb-8844-42ec2cd146e2.png)

Snowflake Open Catalog アカウントの URL を取得します。

```sql
-- カウントの URL を取得
SHOW ACCOUNTS LIKE 'manabian_opencatalog_00_account';
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/57b6f82d-8442-4a9c-a779-8cde911feb82.png)

作成直後はアクセスすると 404 エラーが出る場合があるので、5 分ほど待ちます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ef82a4e3-a847-40c7-97a4-4452c453f682.png)

待機後、設定したアカウントでログインし、Snowflake Open Catalog のページに接続できることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/722917b3-a274-4f94-a891-f28aa4848d39.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ed51664b-3a4f-42a6-bb9a-a32a2a1639c2.png)

#### 外部カタログの作成

Snowflake Open Catalog 上部メニューの `Catalogs` タブを開き、`+ Catalog` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1aeb1b51-9b15-4a33-9b91-c277dfdf53de.png)

#### カタログの設定

| #    | 項目                            | 設定値例                                                     | 備考                                                   |
| ---- | ------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------ |
| 1    | Name                            | manabian_sf_sync_catalog                                    | カタログの名称                                         |
| 2    | External                        | チェック                                                     | 外部カタログとして扱うかどうか                          |
| 3    | Storage  provider               | Azure                                                        |                                                        |
| 4    | Default  base location          | `wasbs://snowflake@snowflakeicebergqiita.blob.core.windows.net/snowflakecatalog/` | Azure プロトコルではなく、 wasbs または abfss を指定     |
| 5    | Additional locations (optional) | 空文字                                                       |                                                        |
| 6    | Azure tenant ID                 | 095ca098-c723-xxxxxx-xxxxxxxxxx                              | Azure テナント ID                                      |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/661a7c6a-e28a-451c-b183-95b12c588acb.png)

:::note info
本記事は Azure 環境を例に示していますが、以下の公式ドキュメントでは各クラウドベンダー向けの手順が案内されています。

- [Azureストレージを使用したカタログの作成| Snowflake Documentation](https://other-docs.snowflake.com/ja/opencatalog/create-catalog#create-a-catalog-using-azure-storage)
- [Amazon Simple Storage Service (Amazon S3)を使用したカタログの作成 | Snowflake Documentation](https://other-docs.snowflake.com/ja/opencatalog/create-catalog#create-a-catalog-using-amazon-simple-storage-service-amazon-s3)
- [Googleのクラウドストレージを使用したカタログの作成 | Snowflake Documentation](https://other-docs.snowflake.com/ja/opencatalog/create-catalog#create-a-catalog-using-cloud-storage-from-google)
:::

:::note info
公式ドキュメント上では Blob と ADLS の両方が指定可能となっていますが、ADLS での動作は未検証です。また、Blob の URI については「abfss」でなく「wasbs」で動作している点に留意してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/2fc0ee8b-d264-492d-a728-f221896c7f65.png)
:::

出所：[Azureストレージを使用したカタログの作成| Snowflake Documentation](https://other-docs.snowflake.com/ja/opencatalog/create-catalog#create-a-catalog-using-azure-storage)

カタログが作成されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/8411c3c9-18d5-4bb5-99a2-e71591767622.png)

#### Azure Storage に対する認証設定

`AZURE_CONSENT_URL` にアクセスし、外部アプリケーションに対してログインの同意を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0d23e6a7-e33c-4bdf-a9cd-d54b76312173.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f9fd4b38-7201-45ba-9f95-2169356bc4a4.png)

:::note info
この手順は、以下ドキュメントにおける「Microsoft ID プラットフォームでのアクセス許可と同意の設定」に相当します。

- [Microsoft ID プラットフォームでのアクセス許可と同意の概要 - Microsoft identity platform | Microsoft Learn](https://learn.microsoft.com/ja-jp/entra/identity-platform/permissions-consent-overview)
:::

#### Azure ポータルでロール割り当て

Azure Storage のページで `アクセス制御 (IAM)` -> `+ 追加` -> `ロールの割り当ての追加` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/01d913c8-a7ee-454a-b4c8-e4f5664ba31b.png)

`ストレージ BLOB データ共同作成者` を選択し、`次へ` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/774ee11b-3851-4712-aa47-7224939236d2.png)

Snowflake Open Catalog のカタログ設定で確認した `AZURE_MULTI_TENANT_APP_NAME` のうち、アンダーバーより前にある名称（例：`mjonvmsnowflakepacint`）で検索し、選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f94f1194-34e7-45de-8ec8-5c12fe76b4e9.png)

Snowflake Open Catalog のカタログ設定に記載されている `AZURE_MULTI_TENANT_APP_NAME` を参照してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0d23e6a7-e33c-4bdf-a9cd-d54b76312173.png)

最後に `レビューと割り当て` をクリックし、`Role assignments` タブで割り当てが追加されたことを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/beb9ed28-ff62-4849-8169-8fd3b6dedd84.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/601c3b0e-74a1-4b01-8bc9-66430acac711.png)

#### Snowflake Open Catalog 上でのロール作成

Snowflake Open Catalog にて、`Connections` -> `Roles` -> `+ Principal Role` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/88731a3f-f8fb-4a39-a6b7-9b86c444816f.png)

`Name` に `snowflake_role` と入力し、`Create` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f52f3655-69af-4eea-b970-f12236753a4d.png)

#### Snowflake Open Catalog 上での接続情報作成

同じく `Connections` -> `Principal` -> `+ Connection` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/27088a43-4f13-4672-8aaf-244c796f9bb3.png)

項目に値を入力し、`Create` をクリックします。

| #    | 項目            | 設定値例           |
| ---- | --------------- | ------------------ |
| 1    | Name            | snowflake         |
| 2    | Query Engine    | snowflake         |
| 3    | Principal Role  | snowflake_role    |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/14c17b94-e777-49fd-b3cd-39bee4ae99af.png)

Snowflake からのアクセス時に使用する `Client ID` と `Client Secret` を取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/8938c66a-a6ad-4852-9ff3-478a85e67372.png)

#### Snowflake Open Catalog のカタログに対する権限付与

`Catalogs` -> 対象のカタログ -> `Roles` -> `+ Catalog Role` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/21a65fbf-2112-4e05-b9c5-0e16b9571c38.png)

以下の項目を設定し、`Create` をクリックします。

| #    | 項目       | 設定値例               |
| ---- | ---------- | ---------------------- |
| 1    | Name       | snowflake_catalog_role     |
| 2    | Privileges | CATALOG_MANAGE_CONTENT |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d6ca57d4-3349-4d50-b191-d062ecafe632.png)

`Grant to Principal Role` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/235aa918-66fa-4366-b0ef-ec08e3631d7f.png)

次の設定を行い、`Grant` をクリックします。

| #    | 項目                   | 設定値例                  |
| ---- | ---------------------- | ------------------------- |
| 1    | Catalog role to grant | snowflake_catalog_role    |
| 2    | Grant to Principal    | snowflake_role            |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/b8cd2835-ecab-45ca-aaf8-f93987dfcac2.png)

### Snowflake Open Catalog のカタログ統合を作成

```sql
-- 各値を変数としてセット
SET open_catalog_account_identifier = 'mtirxwm-manabian_opencatalog_00_account';
SET catalog_name = 'manabian_sf_sync_catalog';
SET client_id = 'OmD7CNsfKOeqt8jAe4QXXXXXX=';
SET client_secret = 'hCfWMmj+b4T5DJvI/uyxXXXXXXX=';

-- 連結した URL は変数に事前に設定
SET full_catalog_uri = 'https://' || $open_catalog_account_identifier || '.snowflakecomputing.com/polaris/api/catalog';


-- 変数を利用してカタログ統合を作成
CREATE OR REPLACE CATALOG INTEGRATION demo_open_catalog_ext  
    CATALOG_SOURCE = POLARIS 
    TABLE_FORMAT = ICEBERG 
    CATALOG_NAMESPACE='default' 
    REST_CONFIG = (
        CATALOG_URI = $full_catalog_uri
        WAREHOUSE = $catalog_name
    )
    REST_AUTHENTICATION = (
        TYPE = OAUTH 
        OAUTH_CLIENT_ID = $client_id 
        OAUTH_CLIENT_SECRET = $client_secret 
        OAUTH_ALLOWED_SCOPES = ('PRINCIPAL_ROLE:ALL')
    ) 
    ENABLED = true;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/54a1482e-95b8-4068-8003-a074dbc5942f.png)

### 既存の Iceberg テーブルを Snowflake Open Catalog に同期

```sql
ALTER ICEBERG TABLE CUSTOMER_ICEBERG SET
    CATALOG_SYNC = 'demo_open_catalog_ext';
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5284e3e5-6255-4aa2-b86f-9b460c595dc6.png)

Snowflake Open Catalog で該当テーブルが表示されることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/2788b4c3-4157-4826-b8e1-5772dd722899.png)

### テーブル作成時にテーブルを Snowflake Open Catalog に同期

テーブル作成時に `CATALOG_SYNC` オプションを指定します。

```sql
CREATE OR REPLACE ICEBERG TABLE nation_iceberg (
  n_nationkey INTEGER,
  n_name STRING
)
    CATALOG = 'SNOWFLAKE'
    EXTERNAL_VOLUME = 'my_azure_sf_volume'
    BASE_LOCATION = 'nation_iceberg'
    CATALOG_SYNC = 'demo_open_catalog_ext'
    AS SELECT
        N_NATIONKEY,
        N_NAME
        FROM
            snowflake_sample_data.tpch_sf1.nation;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9edd8682-064f-486a-a879-474fffe52765.png)


:::note info

データベースやスキーマレベルで同期が必要な場合は対象のスコープで ALTER SET CATALOG SYNC を実施します

引用：https://docs.snowflake.com/en/user-guide/tables-iceberg-open-catalog-sync#set-up-catalog-sync-at-the-database-level

:::



Snowflake Open Catalog で新たに作成したテーブルが確認できれば完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/26b69bb6-28d9-44ee-ad2c-320530e4d3cb.png)