dbt では SQL 以外に Python でも model を書くことができるが、 Python コードの処理は dbt が行うわけではない。
外部の実行環境に Python コードを送信し、そこで処理を行う。
データプラットフォーム毎に「外部の実行環境」が用意されており、 BigQuery の場合は Dataproc や BigQuery DataFrames を使う。
Dataproc クラスタで Python model を処理する方法は以前書いた。
しかし、高い処理能力が求められるようなユースケースでない場合、 Dataproc や BigQuery DataFrames は過剰に感じることが多い。
単純に、インフラを管理しなければならなくなる。Dataproc サーバーレスや BigQuery DataFrames は Dataproc クラスタに比べれば軽量だとは思うが、 Google Cloud の各種リソースの管理や設定が発生することに変わりはない。
また、ユーザーが自分で定義した Python 関数を Python model でimportすることができない、という問題もある。Dataproc クラスタの初期化スクリプトを使ってインストールさせる、という方法はあるが、冗長だし、importしたい関数が増えたり変わったりした場合は、その都度クラスタの設定を変えて作り直さないといけない。
dbt-fal というライブラリがあり、これを使うことで上記の問題を解決できた。
外部のインフラを必要とせずに Python model を実行できるので扱いやすく、ポータビリティも高い。
しかし 2024 年 4 月に開発が終了してしまった。PyPI ライブラリとして配布されているので現在もインストールして利用することはできるが、 dbt-core のv1.5(既に EOL)までしか対応していない。
そこで、 dbt-fal を参考にして自分で代用品を作った。
dbt-core のv1.11(2026/02/18 現在での最新バージョン)に対応している。
現時点では BigQuery にしか対応していない。これは、私が今のところ BigQuery 以外のデータプラットフォームを使う予定がないため。
dbt-fal も dbt-pal も、dbt の Adapter として作られている。
Adapter とは、dbt がデータプラットフォーム(BigQuery や Snowflake など)とやり取りするためのプラグイン。dbt-core にはデータプラットフォームとやり取りする機能はなく、 Adapter がそれを担う。データプラットフォーム毎に Adapter を用意し、それがデータプラットフォームとのやり取りを行う。例えば BigQuery の場合はdbt-bigqueryという Adapter を使う。
どの Adapter を使うかは、profiles.ymlのtypeフィールドで指定する。
例えば以下のように書いた場合、bqという target ではdbt-bigqueryを使う。target には他に、接続先など、データプラットフォームに関する情報が記述されるが、 Adapter はこれらの情報を使ってデータプラットフォームとのやり取りを行う。
my_project: target: bq outputs: bq: type: bigquery method: oauth project: my-project dataset: my_dataset location: asia-northeast1
先述したように dbt-fal も dbt-pal も Adapter として作られているが、データプラットフォームに関する情報は保持しない。Adapter をラップする Adapter、のような実装になっており、データプラットフォームに関する情報の保持や通信処理を、他の Adapter に委譲する仕組みになっている。
dbt-pal を使う場合、profiles.ymlにはtypeフィールドの他にdb_profileフィールドを書く必要がある。db_profileフィールドには他の target を書き、その target に書かれた Adapter や接続情報が使用される。
そのため以下のように書いて--target palで dbt を実行すると、dbt-core は内部的に dbt-pal と dbt-bigquery の両方を使うことになる。
my_project: target: bq outputs: pal: type: pal db_profile: bq bq: type: bigquery method: oauth project: my-project dataset: my_dataset location: asia-northeast1
dbt-core とやり取りするのは dbt-pal だが、接続情報を持っているのは dbt-bigquery であり、処理の大部分も dbt-bigquery に委譲される。
唯一、 Python model の処理のみを dbt-pal が行う。dbt-bigquery の場合は Python model のコードを Google Cloud に送信するが、dbt-pal はそうではなく dbt を実行しているプロセスでそのまま処理する。そのため他の.pyファイルを import できるし、 Google Cloud 側の追加対応も不要になっている。
より詳しい内容についてコード中にコメントを書いているので、そちらも参照のこと。
https://github.com/numb86/dbt-pal/blob/v0.2.0/src/dbt/adapters/pal/impl.py