dbtのCLI版をインストールして使ってみた

like a developer
2021.01.05

大阪オフィスの玉井です。

私は、今まで、WebベースのCloud版のdbtしか使ったことがありませんでした。実は、Cloud版は最近登場したバージョンで、当初はCLI版(ローカルにインストールしてコマンドベースで操作)しかありませんでした。CLI版は今も存在しており、いつでも無料でインストール・使用することができます。CLI版は、任意のコードエディタ等で、ローカルで開発を行うことができるため、よりソフトウェア開発者っぽくdbtを使うことが出来ます。

というわけで、今回はdbt CLIを実際にインストールしてみました。

環境

OS

  • macOS Catalina 10.15.7

この記事に書いている検証をするにあたって予めインストールしておく必要があるもの

  • Homebrew
  • Git
  • Google Cloud SDK

公式ドキュメント

やってみた

インストール

公式ドキュメントによれば、インストール方法は3つありますが、今回はHomebrewを使って、サクッとインストールしたいと思います。

$ brew tap fishtown-analytics/dbt
$ brew install dbt

正常にインストールされているかどうか確認します。

$ dbt --version
installed version: 0.18.1
   latest version: 0.18.1

Up to date!

Plugins:
  - bigquery: 0.18.1
  - snowflake: 0.18.1
  - redshift: 0.18.1
  - postgres: 0.18.1

profile.ymlを作成する

dbtは、接続したDWHにデータモデルを生成するツールですので、使用するDWHの接続情報を設定する必要があります。Cloud版はGUIで設定を進めますが、CLI版はprofile.ymlという設定ファイルを用意して、そこに接続情報を記述する形になります。

デフォルト設定だと、dbtは~/.dbt/下にprofile.ymlが存在する前提になっています。ですので、こちらにprofile.ymlを用意します。

profile.ymlの中身

記述する内容は、DWHによって異なります。今回はBigQueryを設定してみます。

my-bigquery-db:
  target: test
  outputs:
    test:
      type: bigquery
      method: oauth
      project: tamai-rei
      dataset: test
      threads: 4
      timeout_seconds: 300
      location: asia-northeast1
      priority: interactive
      retries: 1

BigQueryの認証について

設定値の意味については、ほとんど名称のまんまですが(詳細は公式ドキュメントにあります)、ここではmethodについて、簡単に説明します。

methodでは、dbtがBigQueryにアクセスする時の認証方法を指定します。3種類の中から選ぶ形になりますが、今回はローカルでちょっと試すだけですので、oauthで行きます。これは、その名の通り、OAuth認証でBigQuery(GCP)にアクセスするものです。そのため、GCPのCLIツールであるgcloudが必要になります。ですので、先にGoogle Cloud SDKをインストールしましょう(これもHomebrewでインストールできます)。

インストールできたら、下記コマンドを実行します。

$ gcloud auth application-default login \
https://www.googleapis.com/auth/cloud-platform,\
https://www.googleapis.com/auth/drive.readonly

実行後、Webブラウザに飛ぶので、そこで個人のGCPの認証を行えばOKです。その権限を持って、dbtはBigQueryにアクセスできるようになります。

ちなみに、dbtプロジェクトを実際に本番運用するとなった場合、ローカル以外のどこかで動作させることになるため、GCP側で別途サービスアカウントを発行して、そちらを使った認証方法をとる必要があります(service-account)。

dbtプロジェクトを作成する

実際にdbtモデルを開発するためには、プロジェクトを作成する必要があります。dbtはdbt initというコマンドで、初期プロジェクトを作成することができます。

$ dbt init test-project

作成したプロジェクトをVSCodeで開くとこんな感じです。

dbt_project.ymlの中をちょっと修正

プロジェクトの大元の設定を司るdbt_project.ymlですが、ちょっとだけ中身を変えます。今回はdbt CLIの動作を検証するだけですので、ほとんど初期のままでいいのですが、接続先として、先程profile.ymlに設定したBigQueryを使うようにしたいので、profileの部分だけ変更します(profile.ymlで設定した接続先情報の名称を書く)。

profile: 'my-bigquery-db'

dbtプロジェクトを実行する

疎通確認

dbt CLIでは、プロジェクトに移動すると、dbtコマンドが実行できます。

まずは、dbtがBigQueryに正しく接続できるかどうかを確認します。

$ dbt debug
Running with dbt=0.18.1
dbt version: 0.18.1
python version: 3.8.7
python path: /usr/local/Cellar/dbt/0.18.1_1/libexec/bin/python
os info: macOS-10.15.7-x86_64-i386-64bit
Using profiles.yml file at /Users/tamai.rei/.dbt/profiles.yml
Using dbt_project.yml file at /Users/tamai.rei/test-project/dbt_project.yml

Configuration:
  profiles.yml file [OK found and valid]
  dbt_project.yml file [OK found and valid]

Required dependencies:
 - git [OK found]

Connection:
  method: oauth
  database: tamai-rei
  schema: test
  location: asia-northeast1
  priority: interactive
  timeout_seconds: 300
  maximum_bytes_billed: None
  Connection test: OK connection ok

dbtプロジェクトを実行して、モデルを作成する

問題なく疎通が確認できたところで、実際にdbtを実行して、BigQueryにデータモデルを作成したいと思います。サンプルで既に存在するモデルを実行するので、そのままdbt runします。

$ dbt run
Running with dbt=0.18.1
Found 2 models, 4 tests, 0 snapshots, 0 analyses, 155 macros, 0 operations, 0 seed files, 0 sources

11:52:49 | Concurrency: 4 threads (target='test')
11:52:49 |
11:52:49 | 1 of 2 START table model test.my_first_dbt_model..................... [RUN]
11:52:54 | 1 of 2 OK created table model test.my_first_dbt_model................ [CREATE TABLE (2.0 rows, 0.0 Bytes processed) in 4.84s]
11:52:54 | 2 of 2 START view model test.my_second_dbt_model..................... [RUN]
11:52:58 | 2 of 2 OK created view model test.my_second_dbt_model................ [CREATE VIEW in 3.43s]
11:52:58 |
11:52:58 | Finished running 1 table model, 1 view model in 15.39s.

Completed successfully

Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2

BigQuery側にデータが作成されました。

(意味わからんくらいデータがしょぼいですが、元々こういうデータになってます…)

作成したデータモデルをテストする

この初期プロジェクトにはテストも定義されています。dbt testでテストクエリを実行して、生成したデータが問題ないかどうかチェックできます。

$ dbt test
Running with dbt=0.18.1
Found 2 models, 4 tests, 0 snapshots, 0 analyses, 155 macros, 0 operations, 0 seed files, 0 sources

11:57:23 | Concurrency: 4 threads (target='test')
11:57:23 |
11:57:23 | 1 of 4 START test not_null_my_first_dbt_model_id..................... [RUN]
11:57:23 | 2 of 4 START test not_null_my_second_dbt_model_id.................... [RUN]
11:57:23 | 3 of 4 START test unique_my_first_dbt_model_id....................... [RUN]
11:57:23 | 4 of 4 START test unique_my_second_dbt_model_id...................... [RUN]
11:57:26 | 3 of 4 PASS unique_my_first_dbt_model_id............................. [PASS in 3.43s]
11:57:27 | 1 of 4 FAIL 1 not_null_my_first_dbt_model_id......................... [FAIL 1 in 4.03s]
11:57:27 | 4 of 4 PASS unique_my_second_dbt_model_id............................ [PASS in 4.22s]
11:57:27 | 2 of 4 PASS not_null_my_second_dbt_model_id.......................... [PASS in 4.65s]
11:57:27 |
11:57:27 | Finished running 4 tests in 6.37s.

Completed with 1 error and 0 warnings:

Failure in test not_null_my_first_dbt_model_id (models/example/schema.yml)
  Got 1 result, expected 0.

  compiled SQL at target/compiled/my_new_project/models/example/schema.yml/schema_test/not_null_my_first_dbt_model_id.sql

Done. PASS=3 WARN=0 ERROR=1 SKIP=0 TOTAL=4

not_null_my_first_dbt_model_idというテストが通りませんでした。これは「my_first_dbt_modelというテーブルのidというカラムにNULLが無いこと」をテストするものです。テスト自体はschema.ymlに定義されています。

models:
    - name: my_first_dbt_model
      description: "A starter dbt model"
      columns:
          - name: id
            description: "The primary key for this table"
            tests:
                - unique
                - not_null
...

そして、この設定によりコンパイルされたテストクエリの場所が、dbt testの実行結果にある(target/compiled/my_new_project/models/example/schema.yml/schema_test/not_null_my_first_dbt_model_id.sql)ので、見てみます。

select count(*) as validation_errors
from `tamai-rei`.`test`.`my_first_dbt_model`
where id is null

(実行するまでもないですが)これをそのままBigQueryで実行してみると、idがNULLのレコードが1件あるのがわかります。テストが通らなかったのがわかりますね。

自分でdbtモデルを追加して、再度dbtを実行してみる

コードエディタで普通にdbtモデルを作成して、再度dbtを実行してみます(モデルの内容はめちゃくちゃ適当です)。

{{ config(materialized='table') }}

select
id + 100 as calc
from {{ ref('my_second_dbt_model') }}

そして再度dbt runをします。BigQueryを見てみましょう。

ちゃんと追加作成したモデルがテーブルとして作成されました。

デベロッパーのようにdbtプロジェクトを開発できる

dbt CLIは、以上のような形でdbtプロジェクトを開発してきます。コードエディタでモデルを書いてくわけですが、全部コードなので、Gitでバージョン管理することができます(というか、Gitでバージョン管理するのが前提)。テストもコードで書けたりするので、ここらへんが「デベロッパー(開発者)のようにデータ変換が開発できる」と言われる所以でしょうか。

dbtプロジェクトの本番運用について

今回の検証では、dbtの実行を手動で行いました。

しかし、完成したdbtプロジェクトは、人間の手から離れたところで、定期的に自動実行するのが普通だと思います。つまり、dbtプロジェクトをどこかにデプロイして、そこで本番運用させる必要があります。

いくつか方法があるので、紹介します。下記以外の方法については公式ドキュメントをどうぞ。

dbt Cloudを使う

Cloud版のdbtは、その名の通り(専用の)クラウド上で動いているので、dbtの開発だけでなく、dbtプロジェクトの定期実行等ができます。

Fivetranのdbt integrationを使う

Fivetran上でdbtプロジェクトを定期実行させることができます。詳細は下記をご覧ください。

ジョブ管理ツールを使う

Apache AirflowやDagster等のオーケストレーションツールを使って、dbtプロジェクトを実行することができます。統合用のプラグインやパッケージとかもあります。

おわりに

作業が全体的に「俺、ソフトウェアエンジニアっぽい」って感じに浸れるので、楽しかったです(酷い感想)。