🤔

BigQueryのInformation Schemaで JOBS は叩けるのに TABLE_STORAGE は叩けないのなぁぜなぁぜ?

2024/11/24に公開

TL;DR

https://iret.media/73609

具体的には、TABLE_STORAGE を叩くためにはオーナーのIAMロールでは不足しており、 BigQuery メタデータ閲覧者 のIAMロールが必要。

はじめに

どうも。マイベストのデータエンジニア snhryt です。かなーり前にRe:dashのコロンは消え、今は Redash が正式名称であることを今週知りました。

今回は、BigQueryを利用している方なら誰しもお世話になっているであろうInformation Schema(以降、IS)に関して、私が実務で少し詰まったポイントについて書いていきたいと思います。

前提として、BigQueryのISには大きく3種類あります。

  1. データセットレベル: 単一データセット内の情報(例: TABLES, PARTITIONS)
    SELECT
      *
    FROM
      dataset_name.INFORMATION_SCHEMA.TABLES
    
  2. リージョンレベル: 複数データセットにまたがった情報(例: JOBS, TABLE_STORAGE)
    SELECT
      *
    FROM
      `region-us`.INFORMATION_SCHEMA.JOBS
    
  3. プロジェクトレベル: プロジェクト全体にまたがった情報(例: SCHEMATA)
    SELECT
      *
    FROM
      INFORMATION_SCHEMA.SCHEMATA
    

このうち、今回は2つ目、リージョンレベルのISをピックアップします。

起こったこと

当時、私はBigQueryのコスト内訳を計算しようとしていました。当社のBigQueryの契約はオンデマンド課金型であり、細かい課金要素はさまざまありますが、中でも(当社の使い方的には)主要なものは以下の2つです。

で、それぞれ別々のISを使って深堀りすることができます。それが、タイトルにもある JOBS(_BY_PROJECT)TABLE_STORAGE(_BY_PROJECT) にあたります。

クエリ課金については、JOBS のスキーマを利用した以下のようなクエリでプロジェクト全体の日毎のクエリ料金が算出できました。[1]

SELECT
  DATE(creation_time, "Asia/Tokyo") AS date,
  -- https://cloud.google.com/bigquery/pricing?hl=ja#on_demand_pricing
  -- ¥150/$ で計算
  FLOOR(
    SUM(total_bytes_processed) / POW(1024, 4) * 6.25 * 150
  ) AS query_cost_jpy,
FROM
  `region-us`.INFORMATION_SCHEMA.JOBS
GROUP BY
  date
ORDER BY
  date

続いて、ストレージ容量課金もさくっとこんな感じのクエリで…

SELECT
  -- https://cloud.google.com/bigquery/pricing?hl=ja#storage
  -- ¥150/$ で計算。クエリ課金とは異なりTiB単位ではなくGiB単位での課金になる
  FLOOR(
    SUM(
      active_logical_bytes / POW(1024, 3) * 0.02
      + long_term_logical_bytes / POW(1024, 3) * 0.01
      + active_physical_bytes / POW(1024, 3) * 0.04
      + long_term_physical_bytes / POW(1024, 3) * 0.02
    ) * 150
  ) AS storage_cost_jpy,
FROM
  `region-us`.INFORMATION_SCHEMA.TABLE_STORAGE

と思っていた矢先に現れたのがこいつでした。

どうして??????????

エラーを受けてトライしたこと

  1. 公式ドキュメントの必要なロールを読み直し → プロジェクトに対する BigQuery メタデータ閲覧者(roles/bigquery.metadataViewer)の IAM ロールが必要 → ワイ「オーナー権限あるしこれは違うなぁ(断言)」
  2. TABLE_STORAGE → TABLE_STORAGE_BY_PROJECT に変更 → エラーメッセージ変わらず
  3. TABLE_STORAGE → TABLE_STORAGE_USAGE_TIMELINE(類似のリージョンレベルのISとして)に変更 → エラーメッセージ変わらず
  4. region-asia-northeast1 に変更 → エラーメッセージ変わらず

ここでギブアップで、Google CloudのCommunity Forumへの質問投稿と、Xでのこの切実なポストに至ります。
https://x.com/snhrytdesu/status/1858682672576688355

懺悔

さて、お気づきでしょうか。私が真実に絶対にたどり着けないことに。それといったら、ジョジョ5部でゴールド・エクスペリエンス・レクイエムを喰らった帝王ディアボロのように。

Forumの回答で私は真実を知るわけですが、結論としては、冒頭に書いたとおり、公式ドキュメントの言う通りにIAMロールを追加しておけばよかったのです。つまり、

ワイ「オーナー権限あるしこれは違うなぁ(断言)」

という思い込みがすべての災いの元凶だったのです。自分の知識を過信し、公式ドキュメントを蔑ろにするというエンジニアとしてはあってはならぬ愚行をしてしまったことをここに懺悔します。

オーナーになくてBigQuery メタデータ閲覧者にあるIAM権限とは

BigQuery メタデータ閲覧者のIAMロールに含まれるIAM権限はたったの12個、うちbigquery.xxx系が9個です。一方で、オーナーに含まれるIAM権限は10,294個、うちbigquery.xxx系は98個です。

これらのdiffをとってみた結果がこちら。

なんと、メタデータ閲覧者のIAMロールに含まれるIAM権限のうち、めちゃくちゃ基本的な(少なくとも私はそう思っていた)

  • bigquery.tables.get
  • bigquery.tables.list

は、どちらもオーナーのIAMロールには含まれていません。そのぐらい含めてくれててもいいのにという思いが湧かなくもないですが、オーナーロールについては公式ドキュメントの IAM basic and predefined roles reference にも以下のように記述があるので、たしかに納得ですね。

All Editor permissions, plus permissions for actions like the following:

  • Completing sensitive tasks, like creating App Engine applications
  • Managing roles and permissions for a project and all resources within the project
  • Setting up billing for a project

The Owner role doesn't contain all permissions for all Google Cloud resources. For example, it doesn't contain permissions to modify your Cloud Billing payment information or create IAM deny policies.

おわりに

今回の教訓は2つです。

  1. 何かがうまくいかないときは、まずは自分の思い込みを疑え
  2. BigQueryを管理者として触りまくる人は、とりあえずBigQuery管理者のIAMロールをつけておこう

少しでも私と同じ轍を踏む人が少なくなるようにという祈りを込めて、本記事の結びとさせていただきます。

We're hiring

こんなちょんぼをしないつよつよなデータエンジニアの皆さんをお待ちしております。現時点での選考意思の有無は問わないので、まずはカジュアルな話からでもぜひ!
https://open.talentio.com/r/1/c/my-best/pages/99801
https://speakerdeck.com/mybestinc/mybest-data-infra-asis-tobe

脚注
  1. 本当はSKU単位でドル円換算レートは決まっているので、一律¥150/$で計算するのはよろしくありません。かつ、月初1TiBは無料など、細かい制球条件もあります。が、ここではいったん概算を弾きたいだけなので、細かいことは無視しています。 ↩︎

Discussion