Databricksジョブでdbtを使う

[Use dbt in a Databricks job \| Databricks on AWS](https://docs.databricks.com/workflows/jobs/how-to-use-dbt-in-workflows.html) [2022/9/1時点]の翻訳です。

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

:::note info
**プレビュー**
本機能は[パブリックプレビュー](https://docs.databricks.com/release-notes/release-types.html)です。
:::

Databricksジョブのタスクとしてdbt Coreのプロジェクトを実行することができます。ジョブのタスクとしてdbt Coreプロジェクトを実行することで、以下のDatabricksジョブクラスターのメリットを享受することができます。

- dbtタスクを自動化し、dbtタスクを含むワークフローをスケジュールします。
- dbtの変換処理を監視し、変換処理のステータスに基づいて通知を送信します。
- 他のタスクを含むワークフローにdbtプロジェクトを取り込みます。例えば、Auto Loaderを用いてデータを取り込み、dbtを用いてデータを変換し、ノートブックタスクでデータを分析するワークフローを構築することができます。
- ログ、結果、マニフェスト、設定を含むジョブ実行から得られるアーティファクトを自動でアーカイブします。

dbtコアに関しては、[dbt documentation](https://docs.getdbt.com/docs/introduction)をご覧ください。

Databricksでは、AWSリージョンeu-west-1、ap-southeast-2、us-east-1、us-west-2でdbtタスクをサポートしています。[Supported Databricks clouds and regions](https://docs.databricks.com/administration-guide/cloud-configurations/aws/regions.html)をご覧ください。

# ワークフローの開発と本格運用

DatabricksのSQLウェアハウスを用いてdbtプロジェクトを開発することをお勧めします。DatabricksのSQLウェアハウスを用いることで、dbtによって生成されたSQLをテストし、dbtによって生成されたクエリーをデバッグするためにSQLウェアハウスのクエリー履歴を活用することができます。お使いの開発環境でdbtプロジェクトを作成するためのdbt Coreや`dbt-databricks`パッケージの使い方に関しては、[Connect to dbt Core](https://docs.databricks.com/integrations/prep/dbt.html)をご覧ください。

プロダクション環境でdbtの変換処理を実行する際には、Databricksジョブのdbtタスクを用いることをお勧めします。デフォルトでは、dbtタスクはシングルノードのジョブクラスター上のdbt Pythonプロセスで実行され、dbtが生成したSQLは選択されたSQLウェアハウスで実行されます。

dbtの変換処理をサーバレスSQLウェアハウス、all-purposeクラスター、[その他のdbtがサポートされるウェアハウス](https://docs.getdbt.com/docs/available-adapters)で実行することができます。本書では最初の2つの選択肢をサンプルとともに説明します。

:::note info
**注意**
SQLウェアハウスでdbtモデルを開発し、プロダクション環境のall-purposeクラスターで実行すると、パフォーマンスとサポート言語の点で若干の差異を体験することになります。all-purposeクラスターにしてもSQLウェアハウスにしても、同じDatabricksランタイムを使用することをお勧めします。
:::

# 要件

- Databricksジョブでdbtプロジェクトを使用する際、[Databricks ReposによるGit連携](https://qiita.com/taka_yayoi/items/b89f199ff0d3a4c16140)をセットアップする必要があります。DBFSからdbtプロジェクトを実行することはできません。
- [サーバレスSQLウェアハウスを有効化](https://docs.databricks.com/sql/admin/serverless.html)する必要があります。
- Databricks SQLの[資格](https://docs.databricks.com/administration-guide/users-groups/users.html#manage-user-entitlements)を有している必要があります。

dbt-sparkパッケージではなく[dbt\-databricks](https://github.com/databricks/dbt-databricks)パッケージを使うことをお薦めします。dbt-databricksパッケージは、Databricksに最適化されたdbt-sparkのforkです。

# 最初のdbtジョブを作成し実行する

以下の例では、コアのdbtのコンセプトをデモンストレーションするサンプルプロジェクトである[jaffle\_shop](https://github.com/dbt-labs/jaffle_shop)プロジェクトを使用します。jaffle shopプロジェクトを実行するジョブを作成するには、以下のステップを実行します。

1. Databricksランディングページに移動し、以下のいずれかを行います。
    - サイドバーの![](https://docs.databricks.com/_images/jobs-icon.png)**Workflows**をクリックし、![](https://docs.databricks.com/_images/create-job.png)をクリックします。
    - サイドバーで![](https://docs.databricks.com/_images/create-icon.png)**Create**をクリックし、メニューから**Job**を選択します。
1. **Tasks**タブに表示されるタスクダイアログボックスで、**Add a name for your job…** をジョブの名前で書き換えます。
1. **Task name**にタスク名を入力します。
1. **Type**で**dbt**タスクタイプを選択します。
![](https://docs.databricks.com/_images/dbt_task_create_task.png)
1. **Source**で**Edit**をクリックし、jaffle shop GitHubリポジトリの詳細を入力します。
![](https://docs.databricks.com/_images/dbt_task_configure_repo_dbt.png)
    - **Git repository URL**でjaffle shopプロジェクトのURLを入力します。
    - **Git reference (branch / tag / commit)** で`main`を入力します。タグやSHAを使うこともできます。
1. **Confirm**をクリックします。
1. **dbt commands**テキストボックスで、実行するdbtコマンド(**deps**, **seed**, **run**)を指定します。コマンドは指定された順序で実行されます。
![](https://docs.databricks.com/_images/dbt_task_configure_commands_serverless.png)
1. **Data warehouse**で、dbtによって生成されるSQLを実行するSQLウェアハウスを選択します。**Data warehouse**ドロップダウンメニューにはサーバレスSQLウェアハウスのみが表示されます。
1. (オプション)タスク出力のスキーマ(データベース)を指定することができます。デフォルトでは、スキーマ`default`が使用されます。
1. (オプション)dbt Coreが実行されるクラスターを変更したい場合、**dbt CLI cluster**をクリックします。コストを最小化するために、クラスターのデフォルトは小規模かつシングルノードのクラスターとなります。
1. (オプション)タスクのdbt-databricksバージョンを指定することができます。例えば、開発用やプロダクションのdbtタスクを特定のバージョンに固定することができます。
    - **Dependent libraries**の下で、現在のdbt-databricksバージョンの隣の![](https://docs.databricks.com/_images/delete-icon.png)をクリックします。
    - **Add**をクリックします。
    - **Add dependent library**で、**PyPI**タブをクリックし、**Package**テキストボックスでdbt-packageバージョンを入力します(`dbt-databricks==1.2.0`など)。
    - **Add**をクリックします。
    ![](https://docs.databricks.com/_images/dbt_task_configure_package_version.png)

    :::note info
    **注意**
    開発と実運用では同じバージョンとなるように、dbtタスクでdbt-databricksのバージョンを固定することをお勧めします。バージョン1.2.0以降のdbt-databricksパッケージを使用することをお勧めします。
   :::

1. **Create**をクリックします。
1. すぐにジョブを実行するには、![](https://docs.databricks.com/_images/run-now-button.png)をクリックします。

# dbtジョブタスクの結果を参照する

ジョブが完了すると、[ノートブック](https://qiita.com/taka_yayoi/items/c306161906d6d34e8bd5#%E3%83%8E%E3%83%BC%E3%83%88%E3%83%96%E3%83%83%E3%82%AF%E3%81%AE%E4%BD%9C%E6%88%90)あるいはDatabricksウェハウスで[クエリー](https://docs.databricks.com/sql/user/queries/queries.html#create-a-query)を実行することによって、SQLクエリーを実行することで結果をテストすることができます。例えば、以下のサンプルクエリーをご覧ください。

```sql:SQL
 SHOW tables IN <schema>;
```

```sql:SQL
SELECT * from <schema>.customers LIMIT 10;
```

`<schema>`をタスクの設定で指定したスキーマ名で置き換えてください。

# APIサンプル

また、dbtタスクを含むジョブを作成、管理するために[Jobs API 2\.1](https://docs.databricks.com/dev-tools/api/latest/jobs.html)を使用することができます。以下の例では、単一のdbtタスクを含むジョブを作成しています。

```json:JSON
{
  "name": "jaffle_shop dbt job",
  "max_concurrent_runs": 1,
  "git_source": {
    "git_url": "https://github.com/dbt-labs/jaffle_shop",
    "git_provider": "gitHub",
    "git_branch": "main"
  },
  "job_clusters": [
    {
      "job_cluster_key": "dbt_CLI",
      "new_cluster": {
        "spark_version": "10.4.x-photon-scala2.12",
        "node_type_id": "i3.xlarge",
        "num_workers": 0,
        "spark_conf": {
          "spark.master": "local[*, 4]",
          "spark.databricks.cluster.profile": "singleNode"
        },
        "custom_tags": {
          "ResourceClass": "SingleNode"
        }
      }
    }
  ],
  "tasks": [
    {
      "task_key": "transform",
      "job_cluster_key": "dbt_CLI",
      "dbt_task": {
        "commands": [
          "dbt deps",
          "dbt seed",
          "dbt run"
        ],
        "warehouse_id": "1a234b567c8de912"
      },
      "libraries": [
        {
          "pypi": {
            "package": "dbt-databricks>=1.0.0,<2.0.0"
          }
        }
      ]
    }
  ]
}
```

# (上級)all-purposeクラスターを用いてdbtによって生成されたSQLを実行する

all-purposeクラスターでdbtタスクを実行するには、接続するクラスターを定義するカスタムの`profiles.yml`を使用します。all-purposeクラスターでjaffle shopプロジェクトを実行するジョブを作成するには、以下のステップを実行します。

1. [jaffle\_shop](https://github.com/dbt-labs/jaffle_shop)リポジトリのforkを作成します。
1. フォークしたリポジトリをデスクトップにコピーします。例えば、以下のようなコマンドを実行します。

    ```bash:Bash
    git clone https://github.com/<username>/jaffle_shop.git
    ```

    `<username>`をあなたのGithubのハンドル名で置き換えてください。

1. `jaffle_shop`ディレクトリに以下のコンテンツを含む`profiles.yml`を作成します。

    ```yaml:YAML
     jaffle_shop:
       target: databricks_job
       outputs:
         databricks_job:
          type: databricks
          method: http
          schema: "<schema>"
          host: "<http_host>"
          http_path: "<http_path>/<cluster_id>"
          token: "{{ env_var('DBT_ACCESS_TOKEN') }}"
    ```

    - `<schema>`をプロジェクトのテーブルのスキーマ名で置き換えます。
    - `<http_host>`を、お使いのSQLウェアハウスの[Connection Details](https://docs.databricks.com/integrations/bi/jdbc-odbc-bi.html#connection-details-sql-warehouse)の**Server Hostname**の値で置き換えます。
    - `<http_path>`を、お使いのSQLウェアハウスの[Connection Details](https://docs.databricks.com/integrations/bi/jdbc-odbc-bi.html#connection-details-sql-warehouse)の**HTTP Path**の値で置き換えます。
    - `<cluster_id>`を接続するクラスターのIDで置き換えます。

    このファイルはソースコントロールにチェックインするので、アクセストークンのようなシークレットを指定しないでください。代わりに、このファイルは実行時に動的に認証情報を挿入するdbtのテンプレート機能を使用します。

1. **Data warehouse**で**None (Manual)** を選択します。
1. **Profiles Directory**では、`profiles.yml`ファイルを格納するディレクトリへの相対パスを入力します。デフォルトのリポジトリルートを使用する場合にはブランクのままとします。
1. このファイルをGitにチェックインし、フォークしたリポジトリにプッシュします。例えば、以下のようなコマンドを実行します。

    ```bash:Bash
    git add profiles.yml
    git commit -m "adding profiles.yml for my Databricks job"
    git push
    ```

1. Databricks UIのサイドバーの![](https://docs.databricks.com/_images/jobs-icon.png)**Workflows**をクリックします。
1. dbtジョブを選択し、**Tasks**タブをクリックします。
1. **Source**で**Edit**をクリックし、フォークしたjaffle shop GitHubリポジトリの詳細を入力します。
![](https://docs.databricks.com/_images/dbt_task_configure_repo.png)
1. **Data warehouse**で**None (Manual)** を選択します。
1. **Profiles Directory**では、`profiles.yml`ファイルを格納するディレクトリへの相対パスを入力します。デフォルトのリポジトリルートを使用する場合にはブランクのままとします。

# エラーとトラブルシューティング

## *プロファイルのファイルが存在しないというエラー*

**エラーメッセージ**

```
dbt looked for a profiles.yml file in /tmp/.../profiles.yml, but did not find one.
```

**可能性のある原因**

指定された$PATHに`profiles.yml`ファイルが見つかりませんでした。dbtプロジェクトのルートに`profiles.yml`ファイルがあることを確認してください。

### Databricks 無料トライアル

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