Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

dbt Core で GCP の出力先プロジェクトと課金プロジェクトを分ける

こんにちは!データサイエンスグループの山本です( @__Y4M4MOTO__ )です。

BigQuery に対して dbt Core を利用している場合、 profiles.yml の project:target variablestarget.project )に設定した GC プロジェクトが dbt run した際のdbtモデルの出力先となる GC プロジェクトであり、かつ課金される GC プロジェクトとなります。

しかし、状況によっては、モデル出力先の GC プロジェクトと課金される GC プロジェクトを分けたいこともあります(例: BigQuery を定額料金で運用している GC プロジェクトがあり、 dev 環境の課金される GC プロジェクトはそちらにしたい)。この記事ではそのようなケースに対応する方法について記しています。

方法

方法は次のとおりです:

  1. profiles.yml の project: に課金先の GC プロジェクトを指定する
  2. 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: については公式ドキュメントの次のページに記載されていますので、詳細はこちらをご確認ください:

docs.getdbt.com

プロファイルが複数ある場合、 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

留意点

上記の方法ですが、次の留意点があります:

  1. dbt モデル内で BigQuery の UDF をプロジェクト ID を省略して参照している場合、 target.project に UDF があると解釈される
  2. dbt の認証を OAuth 認証で行っている場合、ローカルの gcloud コマンドに設定している GC プロジェクトは dbt の課金先の GC プロジェクトではない

1点目について。例えば、 target.projectproject-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 にしたい」といったケースはそれなりに発生するのではないかと思います。そのようなときに本記事が参考になれば幸いです。

ここまでお読みいただきありがとうございました。