Snowflakeのシェア(データ共有)に関するメモ (Architect)

## これは何？

Snowflakeのシェア(データ共有)に関してまとめてみたメモ。

## 公式情報

- 前提
    - シェア元 : プロバイダー と表現する
    - シェア先 : コンシューマー と表現する
- [Snowflakeでのデータ共有の概要](https://docs.snowflake.com/ja/guides-overview-sharing)
    - [Secure Data Sharing(直接共有)](https://docs.snowflake.com/ja/user-guide/data-sharing-intro)
        - 同じSnowflakeリージョン内の1つ以上のアカウントと共有する
    - [listings(リスト)](https://other-docs.snowflake.com/ja/collaboration/collaboration-listings-about)
        - Secure Data Sharing に幾つかの機能が追加されたもの
        - 共有と追加のメタデータをデータ製品として、任意のリージョンの1つ以上のアカウントに提供する
        - クラウド全体で任意のSnowflakeリージョンのユーザとデータを共有する
    - [Data Exchange(データ交換)](https://docs.snowflake.com/ja/user-guide/data-exchange)
        - アカウントのグループを設定・管理し、そのグループに共有を提供する
        - 招待した特定のメンバーのグループとデータを安全にコラボレーションする
- [共有データベースの一般的な制限](https://docs.snowflake.com/ja/user-guide/data-share-consumers#general-limitations-for-shared-databases)
    - 共有データベースは`読み取り専用`
    - 共有データベースの`コメント編集`もできない
    - 共有データベースは`複製(レプリケーション)`できない
    - 共有データベースまたはデータベース内のスキーマ/テーブルの`クローンは作成できない`
    - 共有データベースまたはデータベース内のスキーマ/テーブルの`タイムトラベル(Time Travel)`は使用できない
    - 共有データベースとデータベース内のすべてのオブジェクトを他のアカウントと`再共有(シェア)できない`


### Secure Data Sharing(直接共有)

- [紹介](https://docs.snowflake.com/ja/user-guide/data-sharing-intro)
    - 共有できるオブジェクト
        - テーブル系
            - テーブル
            - 外部テーブル (External tables)
            - 動的テーブル (Dynamic tables)
            - (英語版マニュアルのみ記載) [Iceberg tables](https://docs.snowflake.com/ja/user-guide/tables-iceberg)
        - ビュー系
            - 安全なビュー、セキュアビュー (Secure views)
            - 安全なマテリアライズドビュー、セキュアマテリアライズドビュー (Secure materialized views)
        - その他
            - 安全なUDFs、セキュアUDFs (Secure user-defined functions)
            - (英語版マニュアルのみ記載) データベース
    - 共有されたオブジェクトはすべて`読み取り専用`
    - 共有データはコピーされない
        - つまりコンシューマーアカウントのストレージを占有しない
    - 共有データのクローン(clone)も作成できない
- [開始](https://docs.snowflake.com/ja/user-guide/data-sharing-gs)
    - 従来のやり方(シェアに含まれるすべてのオブジェクトにアクセスできる)
        - 共有の作成([CREATE SHARE](https://docs.snowflake.com/ja/sql-reference/sql/create-share))
            - `CREATE SHARE <シェア名>;`
        - 共有するアカウントを追加する([ALTER SHARE](https://docs.snowflake.com/ja/sql-reference/sql/alter-share))
            - `ALTER SHARE <シェア名> ADD ACCOUNTS=<コンシューマーのアカウント>;`
    - 新しいやり方(シェアに含まれるオブジェクト毎に細かく権限を制御する)
        - データベースロールの作成([CREATE DATABASE ROLE](https://docs.snowflake.com/ja/sql-reference/sql/create-database-role))
            - `CREATE DATABASE ROLE <データベース名>.<データベースロール名>;`
        - データベースロールに権限を付与([GRANT ...](https://docs.snowflake.com/ja/sql-reference/sql/grant-privilege))
            - `GRANT USAGE ON SCHEMA <データベース名>.<スキーマ名> TO DATABASE ROLE <データベース名>.<データベースロール名>;`
            - `GRANT SELECT ON TABLE <データベース名>.<スキーマ名>.<テーブル名> TO DATABASE ROLE <データベース名>.<データベースロール名>;`
        - 共有の作成([CREATE SHARE](https://docs.snowflake.com/ja/sql-reference/sql/create-share))
            - `CREATE SHARE <シェア名>;`
        - 共有にUSAGE権限を付与([GRANT ...](https://docs.snowflake.com/ja/sql-reference/sql/grant-privilege))
            - `GRANT USAGE ON DATABASE <データベース名> TO SHARE <シェア名>;`
        - データベースロールを共有に追加([GRANT DATABASE ROLE ...](https://docs.snowflake.com/ja/sql-reference/sql/grant-database-role-share))
            - `GRANT DATABASE ROLE <データベース名>.<データベースロール名> TO SHARE <シェア名>;`
        - 共有するアカウントを追加する([ALTER SHARE](https://docs.snowflake.com/ja/sql-reference/sql/alter-share))
            - `ALTER SHARE <シェア名> ADD ACCOUNTS=<コンシューマーのアカウント>;
`
- [共有の消費](https://docs.snowflake.com/ja/user-guide/data-share-consumers) : 共有されたものを取り込んで使う時の話
    - 従来のやり方
        - シェアからDBを作成する([CREATE DATABASE](https://docs.snowflake.com/ja/sql-reference/sql/create-database))
            - `CREATE DATABASE <データベース名> FROM SHARE <プロバイダーのアカウント>.<シェア名>`
        - シェアから作成したDBにアクセスする権限を付与([GRANT ... / IMPORTED PRIVILEGES](https://docs.snowflake.com/ja/sql-reference/sql/grant-privilege#usage-notes))
            - `GRANT IMPORTED PRIVILEGES ON DATABASE <データベース名> TO ROLE <ロール名>;`
    - 新しいやり方(データベースロールを使うやり方)
        - シェアからDBを作成する([CREATE DATABASE](https://docs.snowflake.com/ja/sql-reference/sql/create-database))
            - `CREATE DATABASE <データベース名> FROM SHARE <プロバイダーのアカウント>.<シェア名>`
        - データベースロールをロールに付与する([GRANT DATABASE ROLE](https://docs.snowflake.com/ja/sql-reference/sql/grant-database-role))
            - データベースに含まれているデータベースロールを確認してから付与する
            - `SHOW DATABASE ROLES IN DATABASE <シェアから作成したデータベース名>;`
            - `GRANT DATABASE ROLE <シェアから作成したデータベース名>.<データベースロール名> TO ROLE <ロール名>;`
- [共有の操作](https://docs.snowflake.com/ja/user-guide/data-sharing-provider)
    - Business Criticalアカウントから他エディション(Business Criticalよりも下位)のアカウントにシェアするときには注意が必要
        - デフォルトではできない
        - シェアオブジェクトのパラメータ`SHARE_RESTRICTIONS`を`FALSE`にするとできる
        - 逆方向(下位エディション -> Business Critical)はオプション無しでできる
        - [別記事](https://qiita.com/changkuhu/private/05b8598c4215dcfecf97)にまとめたのでそちら参照
    - リージョン間/クラウドベンダー間でのシェアにも注意が必要
        - Snowflakeのデータ複製(レプリケーション)機能を活用して実現する
        - リージョンごとにデータセットのコピーを1つだけ作成する
            - 同じリージョン内にいるコンシューマーにはいくらでも共有できる
        - アカウントで複製を[有効化](https://docs.snowflake.com/ja/user-guide/account-replication-config#label-enabling-accounts-for-replication)しておくこと(ORGADMINが必要)
        - 流れ
            - 複製グループを作成し、データベースと共有を追加する([CREATE REPLICATION GROUP / ALLOWED_SHARES](https://docs.snowflake.com/ja/sql-reference/sql/create-replication-group))
            - コンシューマーアカウントのリージョン(共有先と同じリージョン)に、データベースと共有のあるグループを複製する([CREATE REPLICATION GROUP](https://docs.snowflake.com/ja/sql-reference/sql/create-replication-group)と[ALTER REPLICATION GROUP](https://docs.snowflake.com/ja/sql-reference/sql/alter-replication-group))
            - 複製先(セカンダリ)の共有オブジェクトに、コンシューマーアカウントを追加して共有する([ALTER SHARE](https://docs.snowflake.com/ja/sql-reference/sql/alter-share))
        - [こちら](https://docs.snowflake.com/ja/user-guide/secure-data-sharing-across-regions-platforms)参照
    - 複数のデータベースを共有するときにも注意が必要
        - [こちら](https://docs.snowflake.com/ja/user-guide/data-sharing-multiple-db)参照
            - 複数データベースを跨いで作成したビュー(セキュアビュー)を共有する時に考慮点がある
    
            - データベースまたぎで参照できるように`GRANT REFERENCE_USAGE`をシェアに追加する必要がある
                - `GRANT REFERENCE_USAGE ON DATABASE <セキュアビューから参照しているデータベース> TO SHARE <シェア名>;`
                - `GRANT SELECT ON VIEW <シェアしたいセキュアビュー> TO SHARE <シェア名>;`
        - [複製自体の考慮点](https://docs.snowflake.com/ja/user-guide/account-replication-considerations)にも注意しておく
            - 特に[外部テーブル](https://docs.snowflake.com/ja/user-guide/account-replication-considerations#replication-and-external-tables)とか注意
                - 外部テーブルがエラーの原因になるので取り除かないといけない
                    - 現在、プライマリデータベースの外部テーブルが原因で、複製または更新操作は失敗しエラーメッセージが表示される
                    - このエラーを回避するには、複製対象に外部テーブルを含めないようにするしかないっぽい
- [CREATE DATABASE / 一般的な使用上の注意 / 共有から作成されたデータベース](https://docs.snowflake.com/ja/sql-reference/sql/create-database#general-usage-notes)
    - PUBLIC または INFORMATION_SCHEMA スキーマはデフォルトではシェアされない(明示的な指定が必要)
    - シェアされたDBは複製(レプリケーション)できない
    - TRANSIENT や DATA_RETENTION_TIME_IN_DAYS などのプロパティは適用されない
        - `TRANSIENT` : 一時テーブル。これはシェアされない
        - `DATA_RETENTION_TIME_IN_DAYS` : Time Travel関係の値。シェアされたテーブルのTime Travel(タイムトラベル)は無効
- [共有タスクの権限](https://docs.snowflake.com/ja/user-guide/security-access-privileges-shares)
    - プロバイダー
        - 従来のやり方
            - [CREATE SHARE](https://docs.snowflake.com/ja/sql-reference/sql/create-share)
            - OWNERSHIP(シェアオブジェクトに、シェアしたいテーブル等を追加/削除したりする権限)
        - 新しいやり方(データベースロールを使うやり方)
            - [CREATE SHARE](https://docs.snowflake.com/ja/sql-reference/sql/create-share)
            - [CREATE DATABASE ROLE](https://docs.snowflake.com/ja/sql-reference/sql/create-database-role)
    - コンシューマー
        - [IMPORT SHARE](https://docs.snowflake.com/ja/user-guide/security-access-privileges-shares#import-share-privilege)
        - [CREATE DATABASE](https://docs.snowflake.com/ja/sql-reference/sql/create-database) : シェアからデータベースを作るときに必要な操作/権限なので、同じロールでシェアの取り込みからそのままデータベース作成まで行う場合はセットになる)

### listings(リスト)
- Secure Data Sharingの強化版ということで、具体的には以下の機能が追加されたもの
    - Snowflake Marketplace で共有を公開できる機能
    - 共有内のデータへのアクセスに対する料金をコンシューマーに請求する機能
    - リストへの関心と共有内のデータの使用状況をモニターする機能
    - 共有に関するメタデータ(タイトル、説明、サンプル SQL クエリ、データプロバイダーに関する情報など)
- [リスト候補オプション](https://other-docs.snowflake.com/ja/collaboration/collaboration-listings-about#listing-availability-options)
    - プライベート
        - 特定のアカウントに共有したいときに選択する
        - `任意のSnowflakeリージョン`のSnowflakeアカウントに直接共有できる
    - 公開
        - Snowflake Marketplaceに公開したいときに選択する
- [リストアクセスオプション](https://other-docs.snowflake.com/ja/collaboration/collaboration-listings-about#listing-access-options)
    - 無料リスト : プライベート、公開で利用できる
    - 有料リスト : プライベート、公開で利用できる
    - 限定トライアルリスト : 公開のみ利用できる
- [プロバイダーについて](https://other-docs.snowflake.com/ja/collaboration/provider-becoming)
    - Snowflake Marketplaceに公開するためには、[プロバイダープロファイル](https://other-docs.snowflake.com/ja/collaboration/provider-becoming#set-up-a-provider-profile)を作成してSnowflakeの承認を受ける必要がある
    - [プロバイダー利用規約の確認および同意](https://other-docs.snowflake.com/ja/collaboration/provider-becoming#label-accept-provider-tos-marketplace)が必要
        - 共有元アカウントでORGADMINを用いて1度だけ実施する
    - リストを公開するロールは、アプリケーションパッケージまたは共有を作成したロールと同じロールでなければならない (共有の`OWNERSHIP`を譲渡できない)
    - リストの操作に[必要な権限](https://other-docs.snowflake.com/ja/collaboration/provider-becoming#privileges-required-for-working-with-listings)
        - リストの作成をするには...
            - 事前にORGADMINを使って、[自動複製(レプリケーション)](https://other-docs.snowflake.com/ja/collaboration/provider-listings-auto-fulfillment#label-delegate-laf-privileges)ができるように設定しておく必要がある
            - ACCOUNTADMINを使う
            - カスタムロールを使用する場合は以下の権限を付与する
                - グローバル権限`CREATE DATA EXCHANGE LISTING`(SQLかSnowsightかどちらでも付与可能)
                - リストの自動複製をするための`MANAGE LISTING AUTOFULFILLMENT` (SQLでのみ付与可能)
                - プロファイルの`OWNERSHIP`か`MODIFY`(Snowsightの操作でのみ付与可能)
                - リストの`OWNERSHIP`か`MODIFY` `USAGE` (Snowsightの操作でのみ付与可能)
    - クラウドベンダーまたぎでシェアする時の考慮
        - [アカウントがクロスクラウドの自動複製を設定できるようにする](https://other-docs.snowflake.com/ja/collaboration/provider-listings-auto-fulfillment#label-delegate-laf-privileges)
            - あらかじめ[クロスクラウドの自動複製を設定する権限を委任](https://other-docs.snowflake.com/ja/collaboration/provider-listings-auto-fulfillment#delegate-privileges-to-set-up-cross-cloud-auto-fulfillment)しておく必要がある
                - ORGADMIN`SYSTEM$ENABLE_GLOBAL_DATA_SHARING_FOR_ACCOUNT`を実行する
- [コンシューマーについて](https://other-docs.snowflake.com/ja/collaboration/consumer-becoming)
    - [Snowflake コンシューマー利用規約に同意](https://other-docs.snowflake.com/ja/collaboration/consumer-becoming#accept-the-snowflake-consumer-terms-of-service)する
    - [必要な権限](https://other-docs.snowflake.com/ja/collaboration/consumer-becoming#set-up-required-privileges)
        - ACCOUNTADMINを使う
        - カスタムロールを使用する場合は以下の権限を付与する
            - `CREATE DATABASE`
            - `IMPORT SHARE`
            - `PURCHASE DATA EXCHANGE LISTING` (有料リストの料金を支払う場合)
            - `IMPORTED PRIVILEGES` (シェアから作成したデータベースにアクセスする場合。シェアから作ったテーブルとかにselectしたい時に必要。)
- [リストの作成/公開](https://other-docs.snowflake.com/ja/collaboration/provider-listings-creating-publishing)
    - リストを作成する要件
        - ↑の「プロバイダーについて」を参照
    - リストの作成
        - Snowsightで作成する(Create Listing)
        - 有料/無料は「How will consumers access the data product?」で選択
    - 特定のコンシューマーにリストを公開する
        - Data -> Provider Studio -> リストを選んでPublish
    - Snowflake Marketplaceにリストを公開する
        - [こちら](https://other-docs.snowflake.com/ja/collaboration/provider-listings-creating-publishing#publish-a-listing-on-the-snowflake-marketplace)参照

### Data Exchange(データ交換/データエクスチェンジ)

- Data Exchangeの有効化(利用開始)は[Snowflakeサポートに問い合わせる](https://docs.snowflake.com/ja/user-guide/data-exchange-requesting)必要がある
- 招待した特定のメンバー(グループ)とデータを共有する(データハブと表現されている)
- [Data Exchange管理者](https://docs.snowflake.com/ja/user-guide/data-exchange-using#data-exchange-admin)
    - Data ExchangeをホストするSnowflakeアカウントのこと
    - メンバーの管理
        - メンバーの[ロール割り当て](https://docs.snowflake.com/ja/user-guide/data-exchange-marketplace-privileges)(プロバイダー、コンシューマー、またはその両方)
- Data Exchangeメンバーシップ
    - このカテゴリの中にプロバイダーとコンシューマーがいる
    - [プロバイダー](https://docs.snowflake.com/ja/user-guide/data-exchange-becoming-a-provider)
        - [プロバイダープロファイルの作成](https://docs.snowflake.com/ja/user-guide/data-exchange-becoming-a-provider#configuring-your-provider-profile)
        - [リストの管理](https://docs.snowflake.com/ja/user-guide/data-exchange-managing-data-listings)
            - リストの作成
            - リストへのアクセスを定義
            - リストを公開
        - [リスト作成の考慮点](https://docs.snowflake.com/ja/user-guide/data-exchange-managing-data-listings#considerations-for-creating-a-listing)
            - テーブル、列、共有名のオブジェクト識別子は、`大文字英数字`のみを使用する
            - リストを公開すると、選択したすべてのリージョンでコンシューマーにリストが表示される
            - リストは自動的に複製される
            - リージョンでデータを共有するには、データを複製するためにそのリージョンのアカウントが必要
            - リージョン間でのデータ共有には、[Snowflakeデータ複製機能](https://docs.snowflake.com/ja/user-guide/secure-data-sharing-across-regions-platforms)を利用する
    - [コンシューマー](https://docs.snowflake.com/ja/user-guide/data-exchange-using#data-consumers)
        - リストの閲覧、探索
        - Snowflake Marketplace <-> Data Exchangeの切り替え
        - データセットの利用
- [Data Exchange管理者の権限](https://docs.snowflake.com/ja/user-guide/data-exchange-marketplace-privileges#granting-provider-privileges-to-other-roles-in-the-snowflake-marketplace-or-a-data-exchange)
    - デフォルトではACCOUNTADMINを使用する
        - メンバーの管理
        - リスト承認リクエストを承認 or 拒否
        - プロバイダープロファイルの承認リクエストを承認 or 拒否
        - カテゴリの表示
    - カスタムロールで実施する場合はData Exchangeの`IMPORTED PRIVILEGES`が必要
        - `GRANT IMPORTED PRIVILEGES ON DATA EXCHANGE <exchange_name> TO <role_name>;`
- [プロバイダーの権限](https://docs.snowflake.com/ja/user-guide/data-exchange-marketplace-privileges#granting-provider-privileges-to-other-roles-in-the-snowflake-marketplace-or-a-data-exchange)
    - Snowflake Marketplace上の特定のコンシューマーとデータやアプリを共有する権限
    - Data Exchange内のデータに関連するさまざまなタスクを実行できるようにする権限
    - デフォルトではACCOUNTADMINを使用する
    - カスタムロールで実施する場合は以下の権限が必要
        - グローバル権限 `CREATE DATA EXCHANGE LISTING`
            - この権限で以下が実行できるようになる
                - リストの作成
                - リストのプロパティの変更
                - リストの表示
                - 受信したリストのリクエストの表示
                - リストのリクエストの拒否
                - 承認のためのリストの送信
                - リストの公開
                - プロバイダープロフィールの作成と表示
        - `CREATE SHARE`
        - `IMPORT SHARE`
        - `PURCHASE DATA EXCHANGE LISTING` (リストを購入する場合に使う)
        - リストの`OWNERSHIP`か`MODIFY` `USAGE`
        - プロバイダープロファイルの`OWNERSHIP`か`MODIFY`
- [コンシューマーの権限](https://docs.snowflake.com/ja/user-guide/data-exchange-using#how-do-i-access-the-data-exchange-to-browse-listings)
    - デフォルトではACCOUNTADMINを使用する
    - カスタムロールで実施する場合は以下の権限が必要
        - `IMPORT SHARE`
        - `IMPORTED PRIVILEGES` (やはりこちらもシェアから作ったオブジェクトにアクセスするのに必要。)
        - シェアからデータベースを作るには`CREATE DATABASE`

## ポイント

### ソリューションに応えられるようにする

要は文章問題。
「ある企業はこのような状態で、このようなことを実現したい。」みたいなことに対して、シェアの特徴を知った上で最も適した解決策を回答する。
もちろん制約を考慮した上で、その手法で解決できるのかも注意しておく。

例 : コンシューマーにて、シェアからデータベースを作成するために必要な権限は？
- CREATE DATABASE
- IMPORT SHARE

`CREATE DATABASE ... FROM SHARE ...` で作成する。

例 : あるグローバル企業では、複数リージョン/複数クラウドベンダーにまたがってSnowflakeを使っている。これらのアカウントにデータを共有するにはどうすればいいか？

- リストかデータ交換で、企業内の全アカウントに共有(プライベート共有)する
- レプリケーションを使って異なるリージョン/クラウドベンダーに共有する

## 所感

いろいろあるなぁ...

- とりあえずリージョンやクラウドベンダーをまたぐならレプリケーション(複製)がポイント
    - 設定にはACCOUNTADMINだけでなくORGADMINも関わる
    - レプリケーション自体の注意点にも色々引っ張られそうなので、現実問題として単純にシェア出来なさそうではある
- カスタムロールに任せるにあたっては諸々権限も押さえておく必要がある
- リストとデータ交換、どっちがええんや
    - データ交換はサポート問い合わせを必要とする...
    - もうリストでええやろ