Unity Catalogによるデータリネージのキャプチャと参照

[Capture and view data lineage with Unity Catalog \| Databricks on AWS](https://docs.databricks.com/data-governance/unity-catalog/data-lineage.html) [2022/12/6時点]の翻訳です。

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

Databricksで実行されたクエリーに対する実行時データリネージをキャプチャするためにUnity Catalogを活用することができます。リネージはすべての言語でサポートされており、カラムレベルまで捕捉されます。リネージデータには、クエリーに関連するノートブック、ワークフロー、ダッシュボードが含まれます。リネージは、ニアリアルタイムでData Explorerに表示され、Databricks REST APIで取得することができます。

リネージはUnity Catalogメタストアにアタッチされているすべてのワークスペースから集約されます。これは、あるワークスペースでキャプチャされたリネージは、メタストアを共有する他のワークスペースで参照できることを意味します。リネージデータを参照するには、ユーザーは適切なアクセス権を持っている必要があります。リネージデータは30日間保持されます。

本書では、Data ExplorerとREST APIを用いたリネージの可視化について説明します。

# 要件

Unity Catalogでデータリネージをキャプチャするには以下のことが必要となります。

- ワークスペースで[Unity Catalogが有効化](https://docs.databricks.com/data-governance/unity-catalog/enable-workspaces.html)され、Premiumプランを用いて起動されている必要があります。
- リネージがキャプチャされるためには、テーブルはUnity Catalogメタストアに登録されている必要があります。
- クエリーはSparkデータフレーム(例えば、データフレームを返却するSpark SQL関数)あるいはDatabricks SQLインタフェースを使用する必要があります。Databricks SQLやPySparkクエリーのサンプルについては、[サンプル](#サンプル)をご覧ください。
- テーブルやビューのリネージを参照するには、ユーザーは当該テーブル、ビューに対する`SELECT`権限が必要となります。[リネージのアクセス権](#リネージのアクセス権)をご覧ください。
- リネージをキャプチャするには、テーブルを用いてデータの作成、変更を行う必要があります。ファイルに直接書き込まれたデータのリネージはキャプチャされません。

# 制限

- Deltaテーブル間のストリーミングはDatabricksランタイム11.2以降でのみサポートされています。
- テーブルがクラウドストレージロケーションで定義されていたとしても、クラウドストレージのファイルに直接データが書き込まれた際にはリネージはキャプチャされません。例えば、`spark.write.save(“s3://mybucket/mytable/”)`はリネージを生成しません。
- リネージは30日間のローリングウィンドウで計算されるため、30日以前にキャプチャされたリネージは表示されません。例えば、ジョブやクエリーがテーブルAからデータを読み込み、テーブルBに書き込みを行った際、テーブルAとテーブルBの間のリンクは30日間のみ表示されます。
- リネージを参照する際、Jobs APIの`runs submit`リクエストを使用するワークフローは利用できません。`runs submit`リクエストを用いる際も、テーブル、カラムレベルのリネージはキャプチャされますが、ジョブ実行に対するリンクはキャプチャされません。
- Delta Live Tablesパイプラインのリネージはキャプチャされません。
- Unity Catalogはベストエフォートでカラムレベルへのリネージをキャプチャします。しかし、カラムレベルのリネージがキャプチャされない場合があり得ます。
- テーブル名が変更されると、テーブル名が変更されたテーブルに対するリネージはキャプチャされません。

# サンプル

:::note
**注意**
- 以下のサンプルでは、カタログ`lineage_data`、スキーマ`lineagedemo`を使用します。別のカタログやスキーマを使用する際には、サンプルの中の名称を変更してください。
- このサンプルを完了するには、スキーマに対する`CREATE`、`USAGE`権限が必要となります。メタストア管理者、カタログのオーナー、スキーマのオーナーがこれらの権限を付与することができます。例えば、グループ`data_engineers`のすべてのユーザーにカタログ`lineage_data`のスキーマ`lineagedemo`へのテーブル作成権限を与えるには、以下のクエリーを実行します。

    ```sql:SQL
    CREATE SCHEMA lineage_data.lineagedemo;
    GRANT USAGE, CREATE on SCHEMA lineage_data.lineagedemo to `data_engineers`;
    ```
:::

## リネージのキャプチャと探索

リネージデータをキャプチャするには、以下のステップを実行します:

1. Databricksのランディングページに移動し、サイドバーの![](https://docs.databricks.com/_images/create-icon.png)**New**をクリックし、メニューから**Notebook**を選択します。
1. ノートブックの名前を入力し、**Default Language**で**SQL**を選択します。
1. **Cluster**で、Unity Catalogにアクセスできるクラスターを選択します。
1. **Create**をクリックします。
1. ノートブックの最初のセルに以下のクエリーを記述します。

    ```sql:SQL
    CREATE TABLE IF NOT EXISTS
      lineage_data.lineagedemo.menu (
        recipe_id INT,
        app string,
        main string,
        dessert string
      );
    
    INSERT INTO lineage_data.lineagedemo.menu
        (recipe_id, app, main, dessert)
    VALUES
        (1,"Ceviche", "Tacos", "Flan"),
        (2,"Tomato Soup", "Souffle", "Creme Brulee"),
        (3,"Chips","Grilled Cheese","Cheesecake");
    
    CREATE TABLE
      lineage_data.lineagedemo.dinner
    AS SELECT
      recipe_id, concat(app," + ", main," + ",dessert)
    AS
      full_menu
    FROM
      lineage_data.lineagedemo.menu
    ```

1. クエリーを実行するには、セルをクリックし**shift+enter**を押すか、![](https://docs.databricks.com/_images/run-menu.png)をクリックして**Run Cell**を選択します。

これらのクエリーによって生成されたリネージをData Explorerで参照するには、以下のステップを実施します。

1. Databricksワークスペースのトップバーにある**Search**ボックスで、`lineage_data.lineagedemo.dinner`と入力し、**Search lineage_data.lineagedemo.dinner in Databricks**をクリックします。
1. **Tables View all tables**の下で、`dinner`テーブルをクリックします。
1. **Lineage**タブを選択します。**Lineage**パネルが表示され、`menu`テーブルが表示されます。
![](https://docs.databricks.com/_images/uc-lineage-menu-table.png)
1. データリネージのインタラクティブなグラフを表示するには、**See Lineage Graph**をクリックします。デフォルトではグラフには1レベルのみが表示されます。更なるコネクションが存在する場合には、ノードの![](https://docs.databricks.com/_images/plus-sign-icon.png)アイコンをクリックします。
1. **Lineage connection**パネルをオープンするために、リネージグラフでノードを接続している矢印をクリックします。**Lineage connection**パネルはソースとターゲットのテーブル、ノートブック、ワークフローを含む接続の詳細を表示します。
![](https://docs.databricks.com/_images/uc-lineage-graph.png)
1. `dinner`テーブルに関連するノートブックを表示するには、**Lineage connection**パネルでノートブックを選択するか、リネージグラフを閉じて**Notebooks**をクリックします。新規タブでノートブックを開くにはノートブック名をクリックします。
1. カラムレベルのリネージを参照するには、関連カラムへのリンクを表示するためにグラフのカラムをクリックします。例えば、カラム`full_menu`をクリックすると派生元の上流のカラムが表示されます。
![](https://docs.databricks.com/_images/uc-lineage-column-lineage.png)

Pythonなど別の言語によるリネージの作成、参照をデモンストレーションするために、以下のステップを実行します。

1. 上で作成したノートブックをオープンし、新規セルを作成し、以下のPythonコードを入力します。
    ```py:Python
    %python
    from pyspark.sql.functions import rand, round
    df = spark.range(3).withColumn("price", round(10*rand(seed=42),2)).withColumnRenamed("id","recipe_id")
    
    df.write.mode("overwrite").saveAsTable("lineage_data.lineagedemo.price")
    
    dinner = spark.read.table("lineage_data.lineagedemo.dinner")
    price = spark.read.table("lineage_data.lineagedemo.price")
    
    dinner_price = dinner.join(price, on="recipe_id")
    dinner_price.write.mode("overwrite").saveAsTable("lineage_data.lineagedemo.dinner_price")
    ```

1. セルをクリックして、**shift+enter**を押すか、![](https://docs.databricks.com/_images/run-menu.png)をクリックして**Run Cell**を選択します。
1. Databricksワークスペースのトップバーにある**Search**ボックスで、`lineage_data.lineagedemo.price`と入力し、**Search lineage_data.lineagedemo.price in Databricks**をクリックします。
1. **Tables**の下の`price`をクリックします。
1. **Lineage**タブを選択し、**See Lineage Graph**をクリックします。SQLやPythonクエリーによって生成されたデータリネージを探索するために![](https://docs.databricks.com/_images/plus-sign-icon.png)アイコンをクリックします。
![](https://docs.databricks.com/_images/uc-expanded-lineage-graph.png)
1. **Lineage connection**パネルをオープンするために、リネージグラフでノードを接続している矢印をクリックします。**Lineage connection**パネルはソースとターゲットのテーブル、ノートブック、ワークフローを含む接続の詳細を表示します。

## ワークフローのリネージのキャプチャと参照

また、Unity Catalogに対して読み書きを行うすべてのワークフローのリネージもキャプチャされます。Databricksワークフローのリネージの参照をデモンストレーションするには、以下のステップを実施します。

1. Databricksのランディングページに移動し、Data Science & Engineeringペルソナに切り替えます。
1. サイドバーの![](https://docs.databricks.com/_images/create-icon.png)**New**をクリックし、メニューから**Notebook**を選択します。
1. ノートブックの名前を入力し、**Default Language**で**SQL**を選択します。
1. **Create**をクリックします。
1. 最初のセルに以下のクエリーを記述します。

    ```sql:SQL
    SELECT * FROM lineage_data.lineagedemo.menu
    ```

1. トップバーの**Schedule**をクリックします。スケジュールのダイアログで**Manual**を選択し、Unity Catalogにアクセスできるクラスターを選択し、**Create**をクリックします。
1. **Run now**をクリックします。
1. Databricksワークスペースのトップバーにある**Search**ボックスで、`lineage_data.lineagedemo.menu`と入力し、**Search lineage_data.lineagedemo.menu in Databricks**をクリックします。
1. **Tables View all tables**の下で`menu`テーブルをクリックします。
1. **Lineage**タブを選択し**Workflows**をクリックして、**Downstream**タブを選択します。`menu`テーブルのコンシューマーとして**Job Name**の下にジョブ名が表示されます。

## ダッシュボードのリネージのキャプチャと参照

SQLダッシュボードのリネージの参照をデモンストレーションするために、以下のステップを使用します。

1. Databricksのランディングページに移動し、サイドバーの**Data**をクリックすることでData Explorerをオープンします。
1. カタログ名をクリックし、**lineagedemo**をクリックし、`menu`テーブルを選択します。また、`menu`テーブルを検索するためにトップバーの検索ボックスを使うこともできます。
1. **Actions > Create a quick dashboard**をクリックします。
1. ダッシュボードに追加するカラムを選択し**Create**をクリックします。
1. Databricksワークスペースのトップバーにある**Search**ボックスで、`lineage_data.lineagedemo.menu`と入力し、**Search lineage_data.lineagedemo.menu in Databricks**をクリックします。
1. **Tables View all tables**の下で`menu`テーブルをクリックします。
1. **Lineage**タブを選択し**Dashboards**をクリックします。`menu`テーブルのコンシューマーとして**Dashboard Name**の下にダッシュボード名が表示されます。

# リネージのアクセス権

リネージグラフは、Unity Catalogと同じ[アクセス権モデル](https://qiita.com/taka_yayoi/items/57589857e22569c56300)を共有します。ユーザーがテーブルに対する`SELECT`権限を有していない場合、リネージを探索することはできません。さらに、参照権限を持つノートブック、ワークフロー、ダッシュボードのみを参照することができます。例えば、管理者ではないユーザー`userA`に対して以下のコマンドを実行するとします。

```sql:SQL
GRANT USAGE on lineage_data.lineagedemo to `userA@company.com`;
GRANT SELECT on lineage_data.lineagedemo.menu to `userA@company.com`;
```

`userA`が`lineage_data.lineagedemo.menu`テーブルのリネージグラフを参照する際、`menu`テーブルを参照することができますが、下流の`lineage_data.lineagedemo.dinner`テーブルのように参照権限を持たないテーブルに関する情報を参照することはできません。`userA`に対して`dinner`テーブルは`masked`ノードとして表示され、`userA`はアクセス権を持たないためテーブルの下流のグラフを展開することはできません。

ワークスペースオブジェクトに対するアクセス権の管理に関しては、[Databricksにおけるワークスペースオブジェクトのアクセスコントロール](https://qiita.com/taka_yayoi/items/2dd6711b7b254505e4a3)をご覧ください。

# リネージデータの削除

:::note alert
**警告！**
以下の手順を実行するとUnity Catalogに格納されているすべてのオブジェクトを削除します。必要な場合にのみこれらの手順を用いるようにしてください。例えば、コンプライアンス要件に対応するためといったことが考えられます。
:::

リネージデータを削除するには、メタストアが管理するUnity Catalogオブジェクトを削除する必要があります。メタストアの削除に関しては[Delete a metastore](https://docs.databricks.com/data-governance/unity-catalog/create-metastore.html#delete)をご覧ください。データは30日以内に削除されます。

# データリネージAPI

データリネージAPIを用いることで、テーブルやカラムのリネージを取得することができます。

:::note warn
**重要！**
Databricks REST APIにアクセスするためには、[認証](https://docs.databricks.com/dev-tools/api/latest/authentication.html)を受ける必要があります。
:::

## テーブルリネージの取得

このサンプルでは`dinner`テーブルのリネージデータを取得します。

### リクエスト

```bash:Bash
curl --netrc -X GET \
-H 'Content-Type: application/json' \
https://<databricks-instance/api/2.0/lineage-tracking/table-lineage \
-d '{"table_name": "lineage_data.lineagedemo.dinner", "include_entity_lineage": true}}'
```

`<databricks-instance>`を、`dbc-a1b2345c-d6e7.cloud.databricks.com`のようなお使いの[ワークスペースインスタンス名](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)で置き換えてください。

このサンプルでは[\.netrc](https://docs.databricks.com/dev-tools/api/latest/authentication.html#netrc)ファイルを使用しています。

### レスポンス

```json:JSON
{
  "upstreams": [
    {
      "tableInfo": {
        "name": "menu",
        "catalog_name": "lineage_data",
        "schema_name": "lineagedemo",
        "table_type": "TABLE"
      },
      "notebookInfos": [
        {
          "workspace_id": 4169371664718798,
          "notebook_id": 1111169262439324
        }
      ]
    }
  ],
  "downstreams": [
    {
      "notebookInfos": [
        {
          "workspace_id": 4169371664718798,
          "notebook_id": 1111169262439324
        }
      ]
    },
    {
      "tableInfo": {
        "name": "dinner_price",
        "catalog_name": "lineage_data",
        "schema_name": "lineagedemo",
        "table_type": "TABLE"
      },
      "notebookInfos": [
        {
          "workspace_id": 4169371664718798,
          "notebook_id": 1111169262439324
        }
      ]
    }
  ]
}
```

## カラムリネージの取得

このサンプルでは`dinner`テーブルのカラムデータを取得します。

### リクエスト

```bash:Bash
curl --netrc -X GET \
-H 'Content-Type: application/json' \
https://<databricks-instance/api/2.0/lineage-tracking/column-lineage \
-d '{"table_name": "lineage_data.lineagedemo.dinner", "column_name": "dessert"}}'
```

`<databricks-instance>`を、`dbc-a1b2345c-d6e7.cloud.databricks.com`のようなお使いの[ワークスペースインスタンス名](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)で置き換えてください。

このサンプルでは[\.netrc](https://docs.databricks.com/dev-tools/api/latest/authentication.html#netrc)ファイルを使用しています。

### レスポンス

```json:JSON
{
  "upstream_cols": [
    {
      "name": "dessert",
      "catalog_name": "lineage_data",
      "schema_name": "lineagedemo",
      "table_name": "menu",
      "table_type": "TABLE"
    },
    {
      "name": "main",
      "catalog_name": "lineage_data",
      "schema_name": "lineagedemo",
      "table_name": "menu",
      "table_type": "TABLE"
    },
    {
      "name": "app",
      "catalog_name": "lineage_data",
      "schema_name": "lineagedemo",
      "table_name": "menu",
      "table_type": "TABLE"
    }
  ],
  "downstream_cols": [
    {
      "name": "full_menu",
      "catalog_name": "lineage_data",
      "schema_name": "lineagedemo",
      "table_name": "dinner_price",
      "table_type": "TABLE"
    }
  ]
}
```

### Databricks 無料トライアル

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