概要
Databricks の UniForm が有効になっているテーブルを、Snowflake の Apache Iceberg テーブル(外部カタログを使用するテーブル)として登録し、別の Snowflake アカウントに共有する手順を紹介します。
本記事は下記記事の一部です。
手順
Databricks 上でテーブルを作成
まず、データベースとテーブルを作成し、データを挿入します。
%sql
CREATE CATALOG IF NOT EXISTS sf_iceberg;
%sql
CREATE TABLE sf_iceberg.default.nation_iceberg (
n_nationkey integer
,n_name string
,n_regionkey integer
,n_comment string
)
TBLPROPERTIES(
'delta.columnMapping.mode' = 'name',
'delta.enableIcebergCompatV2' = 'true',
'delta.universalFormat.enabledFormats' = 'iceberg'
);
%sql
INSERT OVERWRITE sf_iceberg.default.nation_iceberg
SELECT
n_nationkey
,n_name
,n_regionkey
,n_comment
FROM
samples.tpch.nation
テーブルのデータを取得できることを確認します。
%sql
SELECT * FROM sf_iceberg.default.nation_iceberg;
Snowflake で利用する Databricks のサービスプリンシパルを作成
Databricks SDK を使用して、Snowflake で利用するサービスプリンシパルを作成します。
from databricks.sdk import WorkspaceClient
client = WorkspaceClient()
service_account = client.service_principals.create(
display_name="snowflake-share-account",
)
print("Service account created with ID:", service_account.id)
次に、このサービスプリンシパルに対してデータベースオブジェクトに対する権限を付与します。
application_id = service_account.application_id
spark.sql(f"""
GRANT USE CATALOG ON CATALOG sf_iceberg
TO `{application_id}`;
""").display()
spark.sql(f"""
GRANT SELECT ON SCHEMA sf_iceberg.default
TO `{application_id}`;
""").display()
続いて、サービスプリンシパルの OAuth シークレットを取得します。まず、Databricks Workspace の右上にあるアカウントメニューから 設定
を選択します。
IDとアクセス
タブを選択し、サービスプリンシパル
の 管理
を選択します。
先ほど作成したサービスプリンシパルを選択します。
シークレット
タブを開き、シークレットを生成
をクリックします。
存続期間を任意の日数に設定し、生成
を選択します。
表示されたシークレットの値を控えます。
共有元 Snowflake にテーブル作成
まず、カタログ統合を作成します。
CREATE OR REPLACE CATALOG INTEGRATION {catalog_integration_name}
CATALOG_SOURCE = ICEBERG_REST
TABLE_FORMAT = ICEBERG
CATALOG_NAMESPACE = 'default'
REST_CONFIG = (
CATALOG_URI = '{workspace_url}/api/2.1/unity-catalog/iceberg',
WAREHOUSE = '{catalog_name}'
)
REST_AUTHENTICATION = (
TYPE = OAUTH
OAUTH_TOKEN_URI = '{workspace_url}/oidc/v1/token'
OAUTH_CLIENT_ID = '{client_id}'
OAUTH_CLIENT_SECRET = '{secret}'
OAUTH_ALLOWED_SCOPES = ('all-apis', 'sql')
)
ENABLED = TRUE;
プレースホルダー | 説明 |
---|---|
{catalog_integration_name} |
カタログ統合の名前を指定します。統合設定を一意に識別するための名称です。 |
{workspace_url} |
Databricks ワークスペースの URL を指定します。 |
{catalog_name} |
Databricks のカタログ名を指定します。 |
{client_id} |
OAuth 認証のクライアント ID を指定します。 |
{secret} |
OAuth 認証のシークレットを指定します。 |
次に、Snowflake で外部 Volume を作成します。
CREATE OR REPLACE EXTERNAL VOLUME {external_volume_name}
STORAGE_LOCATIONS = (
(
NAME = '{name}'
STORAGE_PROVIDER = 'AZURE'
STORAGE_BASE_URL = 'azure://{azure_storage_account_name}.blob.core.windows.net/{azure_storage_container_name}'
AZURE_TENANT_ID = '{tenant_id}'
)
);
プレースホルダー | 説明 |
---|---|
{external_volume_name} |
Snowflake の外部 Volume 名を指定します。 |
{name} |
Snowflake の外部 Volume の名前を指定します。 |
{azure_storage_account_name} |
Azure ストレージアカウントの名前を指定します。 |
{azure_storage_container_name} |
Azure ストレージアカウントのコンテナ名を指定します。 |
{tenant_id} |
Azure のテナント ID を指定します。 |
続いて、下記クエリで AZURE_CONSENT_URL
の値を取得します。
DESC EXTERNAL VOLUME azure_sf_share_exvol;
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';
Azure にログインしているブラウザで AZURE_CONSENT_URL
にアクセスし、表示された画面で 承諾
を選択します。
すると、このサービスプリンシパルが Azure テナントに追加されます。そのため、必要に応じてストレージに対する権限(例:ストレージ BLOB データ共同作成者
)を付与します。
外部 Volume へのアクセスが問題なく行えるか、下記クエリで確認します。
SELECT SYSTEM$VERIFY_EXTERNAL_VOLUME('azure_sf_share_exvol');
次にデータベースを作成します。
CREATE DATABASE IF NOT EXISTS databricks_uf_share_db;
USE databricks_uf_share_db;
Databricks の UniForm が有効なテーブルを、Snowflake 上で Iceberg テーブルとして作成します。
CREATE OR REPLACE ICEBERG TABLE nation_iceberg_from_db_by_uf
EXTERNAL_VOLUME = 'azure_sf_share_exvol'
CATALOG = 'databricks_uniform_catalog_integration'
CATALOG_TABLE_NAME = 'nation_iceberg'
CATALOG_NAMESPACE = 'default'
AUTO_REFRESH = TRUE;
テーブルからデータが正しく取得できることを確認します。
SELECT * FROM nation_iceberg_from_db_by_uf;
データ共有先アカウントを作成
はじめに、ORGADMIN
ロールに切り替えます。
-- ORGADMIN にカレントロールを変更
USE ROLE ORGADMIN;
SELECT CURRENT_ROLE();
データ共有先の Snowflake アカウントを新規で作成します。
-- データ共有先の Snowflake アカウントを作成
-- ToDo EMAIL と REEGION をかえる必要あり
CREATE ACCOUNT manabian_comsumer_01_account
ADMIN_NAME = 'comsumer_admin'
ADMIN_PASSWORD = 'MySecurePassword2025!'
EMAIL = 'admin@example.com'
MUST_CHANGE_PASSWORD = FALSE
EDITION = ENTERPRISE
REGION = 'AZURE_EASTUS2';
次に、データ共有先の新アカウントの URL を取得します。
-- アカウントの URL を取得
SHOW ACCOUNTS LIKE 'manabian_comsumer_01_account';
上記で作成したアカウントにログインします。
ワークスペースで下記クエリを実行し、Data Sharing Account Identifier
の値を取得します。必要に応じてクラスタを作成してください。
SELECT
CURRENT_ORGANIZATION_NAME() || '.' || CURRENT_ACCOUNT_NAME() AS "Data Sharing Account Identifier";
共有元 Snowflake アカウントにて共有の作成と権限付与
共有を作成します。
CREATE OR REPLACE SHARE db_by_uf_share;
続いて、共有に対する権限を付与します。
GRANT USAGE ON DATABASE databricks_uf_share_db TO SHARE db_by_uf_share;
GRANT USAGE ON SCHEMA databricks_uf_share_db.public TO SHARE db_by_uf_share;
GRANT SELECT ON ICEBERG TABLE nation_iceberg_from_db_by_uf TO SHARE db_by_uf_share;
先ほど取得した Data Sharing Account Identifier を使用して、共有先アカウントがこの共有を利用できるよう設定します。
-- 共有先アカウントで取得した Data Sharing Account Identifier の値をセット
SET data_sharing_account_identifier = 'LAMPVRN.MANABIAN_COMSUMER_01_ACCOUNT';
ALTER SHARE db_by_uf_share
ADD ACCOUNTS = $data_sharing_account_identifier;
共有先 Snowflake アカウントにて共有に基づきデータベースを作成
共有先の Snowflake アカウントで、ACCOUNTADMIN
ロールに切り替えます。
USE ROLE ACCOUNTADMIN;
SELECT CURRENT_ROLE();
次に、NAME
が DB_BY_UF_SHARE
の owner_account_and_name
を確認します。
SHOW SHARES;
SELECT
CONCAT($3, '.', $4) AS owner_account_and_name
,$3 AS owner_account
,$4 AS name
FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));
取得した owner_account_and_name
をもとに、共有されたテーブルを含むデータベースを作成します。
CREATE OR REPLACE DATABASE SHARE_BY_DB_UF_DB
FROM SHARE LAMPVRN.OFA41652.DB_DELTA_UF_SHARE;
USE DATABASE SHARE_BY_DB_UF_DB;
テーブルにアクセスできるか確認します。
SHOW TABLES IN DATABASE SHARE_BY_DB_UF_DB;
SELECT * FROM NATION_ICEBERG_FROM_DB_BY_UF;
Databricks にて DELETE 実行後の 共有先 Snowflake の反映確認
Databricks 側でテーブルのデータを削除してみます。
%sql
DELETE FROM sf_iceberg.default.nation_iceberg WHERE n_nationkey > 3;
共有先の Snowflake でデータが反映されているか確認します。
SELECT count(*) FROM NATION_ICEBERG_FROM_DB_BY_UF;