今日のゴール
- DatabricksのUnityCatalogのデータをSnowflakeから読み込む。
- SnowflakeからDatabricksへTable単位で書き込む。
- DatabricksにdbtからTable作成し、Snowflakeから読み込む。
用意するもの
- AWS (ご自分の環境)
- IAM
- policy
- Role
- S3
- IAM
- Databricks (Free Edition)
- Snowflake (Trial / AWS Enterprise Edition / Oregon)
- dbt (free account or dbtCore)
DataBricks の作業内容
- S3 を使用する外部ロケーションを作成
- Iceberg 読み取りを有効にする Delta テーブルを作成
- OAuth シークレットを作成
- メタストアでの外部データ アクセスを有効にする
Snowflake の作業内容
- カタログ統合を作成
- 外部ボリュームを作成
- カタログリンクデータベースを作成
AWS 詳細
AWS S3
- bucketを1つ作成しておく(eg. "databricks-snowflake-bucket")
- AWSのリージョン注意(Snowflakeの設定参照)
AWS IAM Policy
作成したS3 bucketに読み書きできる権限をRoleにつければOK
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": [
"arn:aws:s3:::<s3-bucket-name>/*",
"arn:aws:s3:::<s3-bucket-name>"
],
"Effect": "Allow"
},
{
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::999999999999:role/<aws-role-name>"
],
"Effect": "Allow"
}
]
}
AWS IAM Role
- 作成したpolicyをDatabricksとSnowflakeが利用しているAWS環境と信頼関係を結ぶ。
( "arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL" はDatabricksの固定のようです。)
あとからDatabricksとSnowflakeの設定してから更新する。 - 作成したRoleのARNを控えておいてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL",
"arn:aws:iam::<YOUR-AWS-ACCOUNT-ID>:role/<THIS-ROLE-NAME>"
]
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<STORAGE-CREDENTIAL-EXTERNAL-ID>"
}
}
}
]
}
Databricks 作業詳細
とりあえずUIを日本語化
- 右上のアイコン(名前のアルファベット) -> Settings(設定) -> Preferences(環境設定) -> Language(言語) -> 日本語
資格情報を作成
-
新規資格情報を作成(Create a credential)
-
新規資格情報を作成画面で入力し、作成ボタンを押す。
-
AWS Roleを更新する。
- 外部IDを"sts:ExternalId"に書き換える(「資格情報が作成されました」画面の信頼ポリシー参照)
-
右上の「構成を検証」ボタンを押すと接続のテスト結果が出るので確認する。
(引っかかりそうなところは、AWS Role、資格情報の作成)

S3 を使用する外部ロケーションを作成
-
カタログ -> + -> 外部ロケーションを作成
-
新しい外部ロケーションを手動で作成
- 外部ロケーション名:<お好きな名前>
- ストレージタイプ:S3
- URL: <>
- ストレージ資格情報:<作成した資格情報>
- コメント:<お好きに>
新規カタログを作成
-
- -> カタログを作成から、以下の内容で作成。
- カタログ名:<お好きに>
- タイプ:Standard
- ストレージの場所:<作成した外部ロケーション>
- サブ/パス:<お好きに>
Iceberg 読み取りを有効にする Delta テーブルを作成
- スキーマ、テーブルの作成
- SQLエディタとかNotebookとか、なんでもいいです。テーブル作成してデータ投入したら、SELECT等で確認しましょう。テーブル作成時に指定したS3のパスにファイルがあることも確認しましょう。
- Delta Lake に格納されたテーブルで Iceberg 読み取りを有効にします。
- Iceberg 形式で使える型はサービスによって異なるので、互換性は注意した方がいいです。
CREATE SCHEMA IF NOT EXISTS DBX_SNOW_CATALOG.ICE_SCHEMA;
USE CATALOG DBX_SNOW_CATALOG;
USE SCHEMA ICE_SCHEMA;
create TABLE dbx_table_01(c1 INT)
USING DELTA
LOCATION 's3://<s3-bucket>/dbx_snow_cat/ice_schema/dbx_table_01/'
TBLPROPERTIES(
'delta.columnMapping.mode' = 'name',
'delta.enableIcebergCompatV2' = 'true',
'delta.universalFormat.enabledFormats' = 'iceberg'
);
insert into dbx_table_01 values (1),(2),(3),(4),(5);
select * from dbx_snow_catalog.ice_schema.dbx_table_01;
OAuth シークレットを作成
- 右上のイニシャルアルファベットアイコンから、設定 -> ワークスペース管理者 -> IDとアクセス -> サービスプリンシパル -> 管理へいきます。
-
「Service Pricipalを追加」を押します。
-
設定タブに移動し、アプリケーションIDを控えます。
サービスプリンシパルに権限設定する
- Snowflakeからの読み書きができるように、Grantつけます。今回はお試し環境なので強権限つけてますが、本番環境へは考慮が必要です。
-- 読み込み用
GRANT USE CATALOG ON CATALOG dbx_snow_catalog TO `<アプリケーションID>`;
GRANT USE SCHEMA ON SCHEMA dbx_snow_catalog.ice_schema TO `<アプリケーションID>`;
GRANT SELECT ON TABLE dbx_snow_catalog.ice_schema.dbx_table_01 TO `<アプリケーションID>`;
-- 書き込み用
grant all privileges on schema dbx_snow_catalog.ice_schema to `<アプリケーションID>`;
grant external use schema on catalog dbx_snow_catalog to `<アプリケーションID>`;
grant all privileges on catalog dbx_snow_catalog to `<アプリケーションID>`;
メタストアでの外部データ アクセスを有効にする
- このあとSnowflakeから
ACCESS_DELEGATION_MODE = VENDED_CREDENTIALSで接続するために、Databricksの該当リージョンのメタストアの外部データアクセスを有効にしておく必要があります。(この設定はリージョン毎に1つなので、共有環境の場合は管理者と相談する必要があります) - カタログ -> 歯車⚙ -> メタストア
Snowflake の作業詳細
カタログ統合を作成
- Iceberg REST カタログ統合を作成します。
CREATE OR REPLACE CATALOG INTEGRATION unity_catalog_int_oauth
CATALOG_SOURCE = ICEBERG_REST
TABLE_FORMAT = ICEBERG
CATALOG_NAMESPACE = 'dbx_snow_catalog' // Snowflakeで使うカタログ名(Databricksのカタログ名)
REST_CONFIG = (
CATALOG_URI = 'https://xxxx.cloud.databricks.com/api/2.1/unity-catalog/iceberg-rest' // DatabricksのワークスペースのURL参照
CATALOG_NAME = 'dbx_snow_catalog'// Databricksのカタログ名
ACCESS_DELEGATION_MODE = VENDED_CREDENTIALS
)
REST_AUTHENTICATION = (
TYPE = OAUTH
OAUTH_TOKEN_URI = 'https://xxxx.cloud.databricks.com/oidc/v1/token' // DatabricksのワークスペースのURL参照
OAUTH_CLIENT_ID = '<クライアントID>'//'<client-id>'
OAUTH_CLIENT_SECRET = '<シークレット>'//'<secret>'
OAUTH_ALLOWED_SCOPES = ('all-apis', 'sql')
)
ENABLED = TRUE
REFRESH_INTERVAL_SECONDS = 30
;
- 確認します。"success":true"になっていればOKです。(エラーの場合は、各所見直しです。。)
SELECT SYSTEM$VERIFY_CATALOG_INTEGRATION('unity_catalog_int_oauth');
外部ボリュームを作成
- S3との連携用に外部ボリューム作成します。
CREATE OR REPLACE EXTERNAL VOLUME s3_dbx_ext_snow_vol
STORAGE_LOCATIONS =
(
(
NAME = 's3_dbx_ext_snow_vol'
STORAGE_PROVIDER = 'S3'
STORAGE_BASE_URL = 's3://<your-s3-bucket>/'
STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::<your-aws-role-arn>'
ENCRYPTION=(TYPE='AWS_SSE_S3')
)
)
ALLOW_WRITES = TRUE;
- 成功したら、以下のSQLでSnowflakeのAWS情報を取り出します(property_valueのjsonに入っています
DESC EXTERNAL VOLUME s3_dbx_ext_snow_vol;
- ご自分のAWS環境のRoleに、上記のJSONの"STORAGE_AWS_IAM_USER_ARN"、"STORAGE_AWS_EXTERNAL_ID"の情報を追記して更新します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL",
"arn:aws:iam::<YOUR-AWS-ACCOUNT-ID>:role/<THIS-ROLE-NAME>",
"arn:aws:iam::<"STORAGE_AWS_IAM_USER_ARN">"
]
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<STORAGE-CREDENTIAL-EXTERNAL-ID>",
"<"STORAGE_AWS_EXTERNAL_ID">"
}
}
}
]
}
- Role更新後、以下のSQLで"success":true" が返ってくればOKです。
SELECT SYSTEM$VERIFY_EXTERNAL_VOLUME('s3_dbx_ext_snow_vol');
カタログリンクデータベースを作成
- 以下のコマンドでデータベースを作成し、成功すると、リンクマークのついたデータベース、Databricksで作成したスキーマ、テーブルがSnowflake上に表示されます。
CREATE DATABASE dbx_cat_db
LINKED_CATALOG = (
CATALOG = 'unity_catalog_int_oauth',
SYNC_INTERVAL_SECONDS = 30
)
EXTERNAL_VOLUME = 's3_dbx_ext_snow_vol';
Databricksで作成したデータの内容を、Snowflakeから確認する。
- SELECTしてデータが表示されればOK
select * from dbx_cat_db."ice_schema"."dbx_table_01";
Snowflakeからテーブルを作成し、データを挿入する。
create or replace ICEBERG TABLE dbx_table_02 (id int)
AUTO_REFRESH = TRUE;
;
insert into dbx_table_02 values (100);
insert into dbx_table_02 values (200);
dbt モデル設定
- Databricsでモデル作成時に、configに以下のように設定を入れると、Iceberg読み取り形式でTable作成することができる。(DatabricksでのTable作成時の設定+α)
{{ config(
tblproperties = {
'delta.columnMapping.mode':'name',
'delta.enableDeletionVectors': 'false',
'delta.enableIcebergCompatV2':'true',
'delta.universalFormat.enabledFormats':'iceberg'
})}}
Select * from hoge
SnowVillage Unconference #8 で発表したときの話
- ざっくりした資料を作って、わいわいディスカッションしてきました。
- Snowflakeからの自動更新時に使われるコンピュートはサーバレスなので、1分課金ではない。
- Icebergはバージョンによってできることがちがう。(勉強が必要だ・・)
参考サイト(ありがとうございます!)
















