Delta Sharingを用いて共有データにアクセスする

[Access data shared with you using Delta Sharing \| Databricks on AWS](https://docs.databricks.com/data-sharing/delta-sharing/recipient.html) [2022/3/11時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

Delta Sharingはセキュアなデータ共有に対するオープンスタンダードです。「データ提供者」と呼ばれるDatabricksユーザーは、「データ受領者」と呼ばれる組織外のユーザー、グループとデータを共有する際にDelta Sharingを使用することができます。コネクターの完全なリスト、使用法に関しては[Delta Sharing](https://delta.io/sharing)のドキュメントをご覧ください。本書では、データ受領者がDatabricks、Apache Spark、pandasを用いてどのようにDelta Sharingで共有されたデータのアクセするのかを説明します。

共有データはDatabricksから直接提供されず、Databricksが稼働しているデータ提供者によって提供されます。

:::note info
**注意**
データ提供者の共有データに対してデータ受領者としてアクセスすることで、データ受領者はデータ提供者によって提供されっるデータ共有にアクセスすることを承認され、(1)データ受領者がそのような共有データを使用することに対して、Databricksがいかなる責任を持たないこと、(2)Databricksがデータ受領者が共有データを使用し、アクセスすることに関する情報(そのようなデータに紐づけられる認証情報ファイルを用いてデータにアクセスしたいかなる個人、企業を含みます)を収集する可能性があり、適切なデータ提供者に共有される可能性があることを許諾したとみなされます。
:::

# 認証情報ファイルをダウンロードする

共有データへのアクセスを許可するためには、データ提供者は認証情報ファイルをダウンロードするアクティベーションURLをあなたに送付します。本書では、共有データにアクセするために、この認証情報ファイルをどのように使用するのかを説明します。

:::note warn
**重要！**
認証情報ファイルは一度しかダウンロードすることはできません。認証情報ファイルをダウンロードした後に再度アクティベーションリンクを開いても、**Download Credential File**ボタンは無効化されます。

- 受領した認証情報ファイルをやアクティベーションリンクを、ご自身の組織外の方に共有しないでください。
- 使用する前にアクティベーションリンクを紛失した場合には、データ提供者にコンタクトしてください。
:::

1. データ提供者によって共有されたアクティベーションリンクをクリックします。お使いのブラウザでアクティベーションページが表示されます。
1. **Download Credential File**をクリックします。

セキュアな場所に認証情報ファイルを保存します。ご自身の組織の他の方と共有する場合には、パスワードマネージャを使用することをお勧めします。

# 共有データを読み込む

認証情報ファイルをダウンロードした後は、データ提供者のDatabricksアカウントに承認を受けるために、お使いのコードでこの認証情報ファイルを使用し、データ提供者が共有したデータを読み込みます。データ提供者がデータ共有を停止するまでアクセスは維持されます。データに対する更新は、あなたに対してニアリアルタイムで反映されます。共有データの読み込み、コピーの作成ができますが、ソースデータを更新することはできません。

以下のセクションでは、Databricks、Apache Spark、pandasを用いてどのように共有データにアクセスするのかを説明します。共有データへのアクセスでトラブルに直面した場合には、データ提供者にコンタクトしてください。

:::note info
**注意**
特に明記しない限り、パートナー連携はサードパーティによって提供されるものであり、あなたはお使いの製品・サービスプロバイダーのアカウントを有している必要があります。Databricksはコンテンツを最新に保つ努力を払いますが、パートナー連携ページのコンテンツの精度やインテグレーションに対してDatabricksは責任を負いません。インテグレーションに関しては適切な提供元にコンタクトしてください。
:::

## Databricksを使う

ノートブックコマンドを用いて、Databricksワークスペースで共有データにアクセスするには、以下のステップを実行します。認証情報ファイルをDBFSに格納し、データ提供者のDatabricksアカウントの承認を得るためにこのファイルを使用し、データ提供者が共有したデータを読み込みます。

この例では、独立して実行する複数のセルを含むノートブックを作成します。同じセルにノートブックコマンドを追加して、順に実行することも可能です。

1. テキストエディタでダウンロードした認証ファイルを開きます。
1. ![](https://docs.databricks.com/_images/workspace-icon.png)**Workspace**をクリックします。
1. フォルダーを右クリックし、**Create > Notebook**をクリックします。
    - 名前を入力します。
    - ノートブックのデフォルト言語をPythonに設定します。これはデフォルトです。
    - ノートブックをアタッチするクラスターを選択します。Databricksランタイム8.4以降が動作しているクラスターか、[Apache Spark connector](https://github.com/delta-io/delta-sharing#apache-spark-connector)ライブラリがインストールされているクラスターを選択します。クラスターライブラリのインストールに関しては、[ライブラリ](https://qiita.com/taka_yayoi/items/d3a46efdc1ad01a581d0)を参照ください。
    - **Create**をクリックします。

    ノートブックエディタでノートブックが開きます。

1. 共有データにアクセスするためにPythonあるいはpandasを使用するには、[delta\-sharing Python connector](https://delta.io/connectors/)をインストールします。ノートブックエディタで以下のコマンドを貼り付けます。

    ```
    %sh pip install delta-sharing
    ```

1. セルのアクションメニュー![](https://docs.databricks.com/_images/cell-actions.png)の一番右にある![](https://docs.databricks.com/_images/run-cell.png)をクリックし、**Run Cell**を選択するか、`shift+enter`を押下します。

    まだ、クラスターにインストールされていない場合、`delta-sharing`をインストールします。

1. ノートブックエディタで、![](https://docs.databricks.com/_images/down-caret.png)をクリックし**Add Cell Below**を選択します。新規セルで認証情報ファイルをDBFSフォルダーにアップロードする以下のコマンドを貼り付けます。以下の変数を置き換えてください。

   - `<dbfs-path>`: 認証情報ファイルを保存するフォルダーのパス
   - `<credential-file-contents>`: 認証情報ファイルの中身 

   認証情報ファイルには3つのフィールド`shareCredentialsVersion`、`endpoint`、`bearerToken`を定義するJSONが含まれています。

    ```
    %scala
    dbutils.fs.put("<dbfs-path>/config.share","""
    <credential-file-contents>
    """)
    ```

1. セルのアクションメニュー![](https://docs.databricks.com/_images/cell-actions.png)の一番右の![](https://docs.databricks.com/_images/run-cell.png)をクリックし、**Run Cell**を選択するか、**shift+enter**を押下します。

    認証情報ファイルがアップロードされた後はこのセルを削除して構いません。全てのワークスペースのユーザーは、DBFSから認証情報を読み取ることができ、全てのクラスター、SQLエンドポイントで認証情報ファイルを利用することができます。セルを削除するには、セルアクションメニューの![](https://docs.databricks.com/_images/cell-actions.png)の一番右にある**x**をクリックします。

1. Pythonを用いて共有内のテーブルを一覧します。ノートブックエディタで![](https://docs.databricks.com/_images/down-caret.png)をクリックし**Add Cell Below**を選択します。
1. 新規セルに以下のコマンドを貼り付けます。`<dbfs-path>`を上のコマンドのパスで置き換えます。

    コードを実行すると、Pythonはクラスター上でDBFSから認証情報ファイルを読み込みます。DBFSは`/dbfs/`のFUSEを用いてマウントされています。

   ```py:Python
   import delta_sharing
   
   client = delta_sharing.SharingClient(f"/dbfs/<dbfs-path>/config.share")
   
   client.list_all_tables()
   ```

1. セルのアクションメニュー![](https://docs.databricks.com/_images/cell-actions.png)の一番右の![](https://docs.databricks.com/_images/run-cell.png)をクリックし、**Run Cell**を選択するか、**shift+enter**を押下します。

    結果はテーブルごとのメタデータを含むテーブルの配列となります。以下の出力では2つのテーブルを表示しています。

    ```
    Out[10]: [Table(name='example_table', share='example_share_0', schema='default'), Table(name='other_example_table', share='example_share_0', schema='default')]
    ```

    出力が空、あるいは期待したテーブルが含まれていない場合には、データ提供者にコンタクトしてください。

1. Scalaを用いて、共有テーブルにクエリーを実行します。ノートブックエディタで![](https://docs.databricks.com/_images/down-caret.png)をクリックし**Add Cell Below**を選択します。新規セルに以下のコマンドを貼り付けます。コードを実行すると、JVMを通じてDBFSから認証情報ファイルが読み込まれます。

    変数を置き換えてください。

    - `<profile_path>`: 認証情報ファイルのDBFSパス。例えば、`/<dbfs-path>/config.share`
    - `<share_name>`: テーブルに対する`share=`の値
    - `<schema_name>`: テーブルに対する`schema=`の値
    - `<table_name>`: テーブルに対する`name=`の値


    ```scala:Scala
    %scala
    spark.read.format("deltaSharing")
       .load("<profile_path>#<share_name>.<schema_name>.<table_name>").limit(10);
    ```

1. セルのアクションメニュー![](https://docs.databricks.com/_images/cell-actions.png)の一番右の![](https://docs.databricks.com/_images/run-cell.png)をクリックし、**Run Cell**を選択するか、**shift+enter**を押下します。

    共有テーブルからロードするたびに、ソースから最新のデータを参照します。

1. SQLを用いて共有データにクエリーを実行するには、最初に共有テーブルからワークスペースにローカルテーブルを作成し、ローカルテーブルに対してクエリーを実行する必要があります。

    共有データはローカルテーブルに格納、キャッシュされません。ローカルテーブルにクエリーを実行するたびに、共有データの現在の状態を参照します。

    ノートブックエディタで![](https://docs.databricks.com/_images/down-caret.png)をクリックし**Add Cell Below**を選択します。

    変数を置き換えてください。

    - `<local_table_name>`: ローカルテーブルの名称
    - `<profile_path>`: 認証情報ファイルのパス
    - `<share_name>`: テーブルに対する`share=`の値
    - `<schema_name>`: テーブルに対する`schema=`の値
    - `<table_name>`: テーブルに対する`name=`の値

    ```sql:SQL
    %sql
    DROP TABLE IF EXISTS table_name;
    
    CREATE TABLE <local_table_name> USING deltaSharing LOCATION "<profile_path>#<share_name>.<schema_name>.<table_name>";
    
    SELECT * FROM <local_table_name> LIMIT 10;
    ```

1. セルのアクションメニュー![](https://docs.databricks.com/_images/cell-actions.png)の一番右の![](https://docs.databricks.com/_images/run-cell.png)をクリックし、**Run Cell**を選択するか、**shift+enter**を押下します。

    コマンドを実行すると、共有データに対して直接クエリーが実行されます。テストとして、クエリーがテーブルに実行され、最初の10行が返却されます。

出力が空、あるいは期待したテーブルが含まれていない場合には、データ提供者にコンタクトしてください。

# Delta Sharingリソースに対するアクセスとアクティビティの監査

[監査ログを設定](https://docs.databricks.com/administration-guide/account-settings/audit-logs.html)した後は、Delta Sharingは監査ログに、いつ誰が共有・受領者を作成、変更、アップデート、削除したのか、受領者がいつアクティベーションリンクにアクセスしたのか、認証情報をダウンロードしたのか、受領者の認証情報がいつローテーションされたのか、期限切れになったのかを記録します。Delta Sharingのアクティビティはアカウントログレベルで記録されます。

1. お使いのアカウントで[監査ログを有効化](https://docs.databricks.com/administration-guide/account-settings/audit-logs.html)します。

   > **重要**
    Delta Sharingのアクティビティはアカウントレベルで記録されます。`workspace_ids_filter`の値を入力しないでください。

    お使いのアカウントでそれぞれのワークスペースに対する監査ログと、アカウントレベルのアクティビティの監査ログが送信されます。ログは設定したS3バケットに送信されます。

1. Delta Sharingのイベントは`serviceName`が`unityCatalog`に設定されます。それぞれのイベントの`requestParams`セクションには、トラブルシューティングするためにデータ提供者に共有できる以下のフィールドが含まれています。

    - `recipient_name`: データ提供者のシステムにおけるデータ受領者名
    - `metastore_id`: データ提供者のシステムにおけるメタストアの名前
    - `sourceIPAddress`: リクエストを行ったIPアドレス

    例えば、以下の監査イベントは受領者が利用できる共有の一覧に成功したことを示しています。この例では、検閲された値は`<redacted>`で置き換えられています。

    ```json:JSON
    {
     "Version":"2.0",
     "auditLevel":"ACCOUNT_LEVEL",
     "Timestamp":1635235341950,
     "orgId":"0",
     "shardName":"<redacted>",
     "accountId":"<redacted>",
     "sourceIPAddress":"<redacted>",
     "userAgent":null,
     "sessionId":null,
     "userIdentity":null,
     "serviceName":"unityCatalog",
     "actionName":"deltaSharingListShares",
     "requestId":"ServiceMain-cddd3114b1b40003",
     "requestParams":{
       "Metastore_id":"<redacted>",
       "Options":"{}",
       "Recipient_name":"<redacted>"
       },
     "Response":{
       "statusCode":200,
       "errorMessage":null,
       "Result":null
     },
     "MAX_LOG_MESSAGE_LENGTH":16384
    }
    ```

以下の表では、データ受領者視点でのDelta Sharingイベントを一覧しています。

| アクション | requestParams |
|:--|:--|
| deltaSharingListShares  |`options`: リクエストで指定されたページネーションのオプション  |
| deltaSharingListSchemas  | `share`: 共有名<br>`options`: リクエストで指定されたページネーションのオプション  |
| deltaSharingListTables  | `share`: 共有名<br>`options`: リクエストで指定されたページネーションのオプション  |
| deltaSharingListAllTables  | `share`: 共有名  |
| deltaSharingGetTableVersion  | `share`: 共有名<br>`schema`: スキーマ名<br>`name`: テーブル名  |
| deltaSharingGetTableMetadata  | `share`: 共有名<br>`schema`: スキーマ名<br>`name`: テーブル名<br>`predicateHints`: クエリーに含まれる述語<br>`limitHints`: 返却する行の最大数  |

以下のDelta Sharingエラーはデータ受領者の観点で記録されます。`<`と`>`の間のアイテムはプレースホルダーのテキストです。

- アクセス権のない共有にユーザーがアクセスしようとしました。

```
DatabricksServiceException: PERMISSION_DENIED:
User does not have SELECT on Share <share_name>`
```

- 存在しない共有にアクセスしようとしました。

```
DatabricksServiceException: SHARE_DOES_NOT_EXIST: Share <share_name> does not exist.
```

- 共有に存在しないテーブルにアクセスしようとしました。

```
DatabricksServiceException: TABLE_DOES_NOT_EXIST: <table_name> does not exist.
```

データ提供者の監査イベント、エラーに関しては[Delta Sharingのリソースに対するアクセスとアクティビティの監査](https://qiita.com/taka_yayoi/items/3a53516c4434c0ee76f0#delta-sharing%E3%81%AE%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8B%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%A8%E3%82%A2%E3%82%AF%E3%83%86%E3%82%A3%E3%83%93%E3%83%86%E3%82%A3%E3%81%AE%E7%9B%A3%E6%9F%BB)をご覧ください。

# Databricks外から共有データにアクセスする

Databricksを使用していない場合、共有データにアクセスするには以下の手順に従ってください。

## Apache Sparkを使う

Apache Spark 3.x以降で共有データにアクセスするには以下の手順を実行してください。

1. あなたに共有されているテーブルの一覧など共有データに関連するメタデータにアクセスするには、[delta\-sharing Python connector](https://delta.io/connectors/)をインストールします。

    ```bash:Bash
    pip install delta-sharing
    ```

1. [Apache Spark connector](https://github.com/delta-io/delta-sharing#apache-spark-connector)をインストールします。
1. 共有内のテーブルを一覧します。以下の例では、`<profile_path>`を認証情報ファイルのパスで置き換えてください。

    ```py:Python
    import delta_sharing
    
    client = delta_sharing.SharingClient(f"<profile_path>/config.share")
    
    client.list_all_tables()
    ```

    結果はテーブルごとのメタデータを含むテーブルの配列となります。以下の出力では2つのテーブルを表示しています。

    ```
    Out[10]: [Table(name='example_table', share='example_share_0', schema='default'), Table(name='other_example_table', share='example_share_0', schema='default')]
    ```

    出力が空、あるいは期待したテーブルが含まれていない場合には、データ提供者にコンタクトしてください。

1. Pythonを用いてSparkで共有データにアクセスします。

    ```py:Python
    delta_sharing.load_as_spark(f"<profile_path>#<share_name>.<schema_name>.<table_name>")

    spark.read.format("deltaSharing")\
    .load("<profile_path>#<share_name>.<schema_name>.<table_name>")\
    .limit(10))
    ```

    変数を以下のように置き換えてください。

    - `<profile_path>`: 認証情報ファイルのパス
    - `<share_name>`: テーブルに対する`share=`の値
    - `<schema_name>`: テーブルに対する`schema=`の値
    - `<table_name>`: テーブルに対する`name=`の値

1. Scalaを用いてSparkで共有データにアクセスします。

    ```scala:Scala
    spark.read.format("deltaSharing")
    .load("<profile_path>#<share_name>.<schema_name>.<table_name>")
    .limit(10)
    ```

出力が空、あるいは期待したテーブルが含まれていない場合には、データ提供者にコンタクトしてください。

## pandasを使う

pandas 0.25.3以降で共有データにアクセスするには以下の手順を踏んでください。

1. あなたに共有されているテーブルの一覧など共有データに関連するメタデータにアクセスするには、[delta\-sharing Python connector](https://delta.io/connectors/)をインストールします。

    ```bash:Bash
    pip install delta-sharing
    ```

1. 共有内のテーブルを一覧します。以下のサンプルでは、`<profile_path>`を認証情報ファイルのパスで置き換えてください。

    ```py:Python
    import delta_sharing
    
    client = delta_sharing.SharingClient(f"<profile_path>/config.share")
    
    client.list_all_tables()
    ```

    出力が空、あるいは期待したテーブルが含まれていない場合には、データ提供者にコンタクトしてください。

1. Pythonを用いてpandasで共有データにアクセスします。以下の例では、変数を以下のように置き換えてください。

    - `<profile_path>`: 認証情報ファイルのパス
    - `<share_name>`: テーブルに対する`share=`の値
    - `<schema_name>`: テーブルに対する`schema=`の値
    - `<table_name>`: テーブルに対する`name=`の値

    ```py:Python
    import delta_sharing
    delta_sharing.load_as_pandas(f"<profile_path>#<share_name>.<schema_name>.<table_name>")
    ```

# 次のステップ

- [Databricksをさらに学ぶ](https://qiita.com/taka_yayoi/items/125231c126a602693610)
- [Delta Sharingをさらに学ぶ](https://delta.io/sharing/)
- [Unity Catalogをさらに学ぶ](https://qiita.com/taka_yayoi/items/15aede468bdca58ec6a3)

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)