ブログ | XIMIX

BigQueryのジョブはどこで動くの?増えすぎたプロジェクトでおこる請求プロジェクトの勘違い

作成者: XIMIX 中根|2023.08.07

日本情報通信の中根です。

本日は私がよくお客様より質問を受けるBigQueryの料金がどこに請求されるかについて解説したいと思います。

今回のテーマと背景

今回のテーマであるBigQueryの料金がどこに請求されるかですがこれは非常に多くの質問をいただきます。

BigQueryは従量課金のサービスであり、意図せず高額な請求が発生することもあるため弊社では利用を開始するにあたりきっちり説明を行います。

ただこの質問はBigQueryをすでにご利用いただいている場合、特に複数のプロジェクトでの利活用、専用のプログラムを開発しているといった普及期に差し掛かっているお客様から質問されることが多いのです。

最初は少ないユースケースのみからスタートしたが、ユーザーや用途が増えるにあたり明確に周知・理解がなされていない状況がカオスを産み、ある日覚えのないクエリ料金が別プロジェクトにて発生している、といったことから質問をいただくことが多いです。

これはBigQueryを利用する上で

  • ジョブ利用ユーザー(サービスアカウント)
  • ジョブを実行する方法
  • ジョブを実行するプロジェクト
  • データが存在するプロジェクト

の考え方がごちゃごちゃになってしまうことから発生します。

特に多いのがサービスアカウントを生成したプロジェクトが請求プロジェクトという誤解です。なぜこのような誤解が発生するのかも含め解説していきます。

最初に覚えること

以下の3つをまずは覚えていただければと思います。

  • ストレージ料金はデータが保存されているプロジェクト
  • 分析料金はBigQueryのジョブを動かしたプロジェクト
  • ジョブを動かしたいプロジェクトは明示的に指定ができる

ストレージ料金について

データが保存されているプロジェクトが請求されるプロジェクトとなります。

こちらは直感的なためあまり間違えることが無いです。

BigQueryのWeb UIからもプロジェクト→データセット→テーブルといった階層構造となりますし、SQL内でも<PROJECT>.<DATASET>.<TABLE>と記載するのでどこにあるかは一目瞭然です。

分析料金について

誤解が多いのが分析料金です。

これはBigQueryのジョブを動かしたプロジェクトが請求プロジェクトとなりますがそもそもどこでジョブが動くのかを理解する必要があります。

ジョブの実行方法毎に考え方、指定の方法が異なるため混乱を招くポイントとなっています。

というのも分析をする方法はどのような物があるでしょうか。

  • Web UIから分析処理を実行する
  • bqコマンドを実行する
  • Client Libraryを利用したプログラムを実行する
  • Jupyter Notebook等でマジックコマンドを実行する

今回は上記4つについてそれぞれ解説してきましょう。

Web UIから分析処理を実行する

もっとも直感的に判別できます。

Web UIはGoogle アカウントをもったユーザーのみが利用できます。

BigQuery Web UIの画面左上のプロジェクトを確認しましょう。そこにあるプロジェクトが請求されるプロジェクトとなります。

Web UIから分析処理を実行する場合のまとめ

Web コンソールにて指定されているプロジェクトを必ず確認しましょう。

bqコマンドを実行する

bqコマンドはCloud SDKを導入することで利用できるCLIコマンドとなります。

コマンドを発行できるユーザーとしてサービスアカウントが加わってきますがまだ考慮は不要です。

bqコマンドの場合以下の順に評価されます。

  1. bq コマンドの--project_idで指定したプロジェクト
  2. gcloud config set project で指定したプロジェクト

1はジョブ単位で明確に指定をするので問題は起きづらいです。

2のgcloud config set project で指定したプロジェクトの場合意図しない動作をすることが多いです。

意図しないケース1: バッチファイルの更新による混入

bqコマンドを利用するケースとしてShell スクリプトにて一連の処理を記載することが多いです。

1つのShellスクリプトの中で複数のプロジェクトを対象としたジョブが動くといったケースとして以下の処理を考えてみましょう

  1. gcloudコンフィグをアクティベーション
  2. A プロジェクトにて課金させたいクエリを実行
  3. B プロジェクトにて課金させたいクエリを実行
  4. A プロジェクトにて課金させたいクエリを実行

この場合gcloud config set project は初期化処理として最初に実行したあとはそのままになりがちです。

Bプロジェクトへのクエリが追加要件として発生した場合BigQuery の課金についてあまり理解されていない方が修正・追加を行うといった背景から紛れ込むことがあります。

こういった場合は明確にbqコマンドにproject_idオプションをつけるように意識をしましょう。

意図しないケース2: bqコマンドを実行するOSユーザーの問題

gcloudコマンドのコンフィグはOSユーザー毎に設定を保存します。

そのため同一のOSユーザーで並行してgcloud config setを実行した場合後続処理にて別のプロジェクトにて実行されたり失敗する場合があります。

なかなかレアケースですが以下のようなケースが考えられます。

バッチA
  1. gcloudコンフィグをAプロジェクト用の設定をアクティベーション
  2. A プロジェクトにて課金させたいクエリを実行(処理時間5分)
  3. Google Cloud以外の内部処理(20分)
  4. A プロジェクトにて課金させたいクエリを実行(処理時間5分)
バッチB
  1. gcloudコンフィグをBプロジェクト用の設定をアクティベーション
  2. Bプロジェクトにて課金させたいクエリを実行(処理時間1分)
処理順序
  1. 10時00分: ジョブ実行OSユーザー batch_user でバッチAを実行
  2. 10時10分: ジョブ実行OSユーザー batch_user でバッチBを実行

この場合10時10分のバッチが失敗したりバッチAの4にて実行されるクエリがBプロジェクトにて実行される場合があります。

これは前述の通りbatch_user というOSユーザーがgcloud config set を実行したタイミングでローカルのコンフィグ設定としてジョブ実行プロジェクトをBプロジェクトに書き換えてしまうからです。

バッチAからはこれを検知することはできないのでバッチBプロジェクトにてジョブを実行してしまいます。

これはなかなか気づきにくいのですがbqコマンドを実行するジョブサーバーを単一ユーザーで運用している場合は特に注意が必要です。

bqコマンドを実行する場合のまとめ

明確にbqコマンドにproject_idオプションをつけるように意識をしましょう。

オプション付与が難しい場合はジョブを実行するユーザーやタイミングについて整理をしましょう。

Client Libraryを利用したプログラムを実行する

Client Libraryの利用のケースではClientのインスタンス化処理および実行するユーザーの情報が重要になります。

PythonのClient Libraryの場合以下の順に評価されます。

  1. インスタンス化したときのprojectパラメータに指定したプロジェクト
  2. 環境変数 GOOGLE_CLOUD_PROJECT もしくは GCLOUD_PROJECTに指定したプロジェクト
  3. サービスアカウント鍵ファイル内のproject_idに記載のあるプロジェクト
  4. 環境変数 GOOGLE_APPLICATION_CREDENTIALSに指定したプロジェク
  5. (Cloud SDKが導入されていたら)gcloud config set projectのプロジェクト
  6. GAE/GCE/CR/CFのメタデータサーバ

1はClientインスタンス化時の指定になります。

ですので1つのコード内にて複数のプロジェクトにてジョブを実行する場合はprojectパラメータへ値を指定できるようにする必要があります。1つのインスタンスを使い回すような作りの場合は注意が必要です。

これはGoogle Cloudのサンプルコードでも`client = bigquery.Client()`とだけ記載があることが多いのでそのまま実装してしまい気づかない or 気づいても改修が大変なのでなかなか直せないといった場合があります。

2以下についてはインスタンス化時に指定していなかった場合にgoogle.auth.default()を呼び出し順次評価します。(参考: GitHub ISSUE)

よくある勘違い: サービスアカウント払い出しプロジェクトが請求プロジェクト

よく勘違いされることとして、BigQueryの分析料金はサービスアカウントを払い出したプロジェクトに請求(≒ジョブが実行)されるというものがあります。

これはまさに上記3が原因となります。

この背景には利用が拡大するにつれ運用ルールのみが伝わり、利用方針やなぜそうなのかといった原理原則が正しく伝えられないことがあります。

クラウドサービスは日々変化していくものなので利用ガイドを配布して終わるのではなく、双方向のやり取りができる場として勉強会や対話会といった啓蒙活動を行っていくことが重要となります。

Client Libraryを利用したプログラムを実行する場合のまとめ

ジョブ実行プロジェクトは非常に重要な要素となるため明示的に指定ができるようにプログラムのI/Fを見直すことを推奨します。

Jupyter Notebook等でマジックコマンドを実行する

マジックコマンドもおおよそ上記同様となります。

  1. %%bigquery --project で指定したプロジェクト
  2. 環境変数 GOOGLE_CLOUD_PROJECT もしくは GCLOUD_PROJECTに指定したプロジェクト
  3. サービスアカウント鍵ファイル内のproject_idに記載のあるプロジェクト
  4. 環境変数 GOOGLE_APPLICATION_CREDENTIALSに指定したプロジェク
  5. (Cloud SDKが導入されていたら)gcloud config set projectのプロジェクト
  6. GAE/GCE/CR/CFのメタデータサーバ

1にてプロジェクトが指定されなかった場合はClient Library同様の処理となります。

こちらはセル単位となるので修正はClient Libraryに比べ容易となることが多いです。

Jupyter Notebook等でマジックコマンドを実行する場合のまとめ

マジックコマンドを利用する場合も明示的に--projectにて指定することを推奨します。

明示的に指定していない場合ノートブックを共有した際に意図しない環境でジョブが稼働してしまう恐れがあることに注意しましょう。

まとめ

非常に長くなりましたが以上がおおよそ抑えるべきポイントとなります。

Client Library については言語毎に実装が異なる可能性があるので念のためソースコードを確認いただければと思います。

ともあれなにごとも

  1. 指定できるオプションがあることを理解する
  2. 指定できる場合は明示的に指定することを心がける
  3. プログラミングにて実装する場合ジョブを実行するプロジェクトを指定できる汎用性のあるI/F実装を心がける

これらを念頭に置くことで誤解やカオスな状況は避けられるでしょう。

ぜひこの記事を読んだことでご自身の環境の見直しのきっかけや話のネタになればと思います。

Google Cloud、Google Workspace に関するご相談はXIMIXへ!

Google Cloud、Google Workspaceに関する お問い合わせはこちら
XIMIX(サイミクス)は商標登録出願中です