こんにちは!データサイエンスグループの山本です( @__Y4M4MOTO__ )です。
BigQuery に対して dbt Core を利用している場合、 profiles.yml の project:
( target variables の target.project
)に設定した GC プロジェクトが dbt run した際のdbtモデルの出力先となる GC プロジェクトであり、かつ課金される GC プロジェクトとなります。
しかし、状況によっては、モデル出力先の GC プロジェクトと課金される GC プロジェクトを分けたいこともあります(例: BigQuery を定額料金で運用している GC プロジェクトがあり、 dev 環境の課金される GC プロジェクトはそちらにしたい)。この記事ではそのようなケースに対応する方法について記しています。
方法
方法は次のとおりです:
- profiles.yml の
project:
に課金先の GC プロジェクトを指定する - dbt_project.yml の
models:
に+database:
の項目を追加し、モデル出力先の GC プロジェクトを指定する
例)
models: your_project: +database: YOUR_OUTPIT_GCP_PROJECT_ID
+database:
はターゲットのデータベース(BigQuery だと target.project
)以外のデータベースにモデルを出力したい場合に使用する設定です。今回の場合、 target.project
に課金先の GC プロジェクト、 +database:
にモデル出力先の GC プロジェクトを指定することで、課金先とモデル出力先の GC プロジェクトを分けることができます。
+database:
については公式ドキュメントの次のページに記載されていますので、詳細はこちらをご確認ください:
プロファイルが複数ある場合、 if 文を使って次のように切り替えることもできます。
例) dev
, stg
というプロファイルがある場合
models: your_project: +database: | {%- if target.name == "dev" -%} YOUR_DEV_GCP_PROJECT_ID {%- elif target.name == "stg" -%} YOUR_STG_GCP_PROJECT_ID {%- else -%} {{ target.project }} {%- endif -%}
dbt を実行した際にどの GC プロジェクトに請求が入ったかは BigQuery のジョブ履歴から確認できます。 INFORMATION_SCHEMA.JOBS_BY_PROJECT
を使うと確認しやすいかと思います。
クエリの一例を以下に示します:
CREATE TEMP FUNCTION timezone() AS ('Asia/Tokyo'); CREATE TEMP FUNCTION today() AS (CURRENT_DATE(timezone())); CREATE TEMP FUNCTION from_date() AS (DATE_SUB(today(), INTERVAL 1 DAY)); CREATE TEMP FUNCTION to_date() AS (DATE_SUB(today(), INTERVAL 1 DAY)); SELECT TIMESTAMP_ADD(TIMESTAMP(creation_time), INTERVAL '9' HOUR) AS creation_time_jst, * FROM `PROJECT_ID`.`region-PROJECT_REGION`.INFORMATION_SCHEMA.JOBS_BY_PROJECT WHERE DATE(creation_time, timezone()) BETWEEN from_date() AND to_date() AND user_email = "YOUR_ADDRESS" ORDER BY creation_time DESC LIMIT 10
留意点
上記の方法ですが、次の留意点があります:
- dbt モデル内で BigQuery の UDF をプロジェクト ID を省略して参照している場合、
target.project
に UDF があると解釈される - dbt の認証を OAuth 認証で行っている場合、ローカルの gcloud コマンドに設定している GC プロジェクトは dbt の課金先の GC プロジェクトではない
1点目について。例えば、 target.project
が project-A
で +database: project-B
と設定している環境で次のような dbt モデルがあったとします。この場合、 udf.yesterday()
は project-A.udf.yesterday()
と解釈されます。
SELECT * FROM hoge_model WHERE dt >= udf.yesterday() -- BigQuery上の "udf" というデータセットに "yesterday()" という UDF を登録している
2点目について。 gcloud コマンドでは次のコマンドでデフォルトで使用する GC プロジェクトを設定することができます。
gcloud config set project PROJECT_ID
ここで設定されている GC プロジェクトは dbt 実行時の請求先ではありません(自分はここを完全に勘違いしてしまっていました…)。
結び
この記事では、 dbt Core で GCP の出力先プロジェクトと課金プロジェクトを分ける方法について記しました。例にも挙げた「 dev 環境では請求先を定額料金の BigQuery にしたい」といったケースはそれなりに発生するのではないかと思います。そのようなときに本記事が参考になれば幸いです。
ここまでお読みいただきありがとうございました。