💲

BigQueryのオンデマンド料金におけるコスト管理方法についてメモ

2023/09/11に公開

what

  • BigQueryにおけるコスト管理方法について、公式ドキュメントを元にメモしたログ
  • 今回はオンデマンド料金について記載のため、定額料金(BigQuery Editions)に関しては記載しない

高額請求が来てしまうパターンとは

よく見かける/耳にするのは以下のような場合(あくまで一例)

  • 大量にデータをスキャンするクエリを実行する
    • select * 系のクエリを投げる
    • (Table Patitionを利用したテーブルの場合)partitionで指定しないでクエリを投げる
  • 料金がかかるクエリをバッチなど利用して連続で実行してしまう
  • Table Patitionを利用しないでテーブルを作成、そこにクエリを投げてしまう事

主に「金額の高くなるクエリを実行した」事によって高額請求になってしまった、という事例が多い。

高額請求がきた事例

https://qiita.com/itkr/items/745d54c781badc148bb9

どうすれば防げるのか

料金体系(どのようにして課金されるのか)」を知り、その上で「費用管理を実施する」事が重要となる。

また、これらを行うことによって費用の削減にもつながる。

  1. BigQueryにおける料金体系の理解
  2. BigQueryにおける費用管理

BigQueryの料金体系

BigQueryの料金(オンデマンド)は大まかに2つに分けられる

  • ストレージ料金(BQに読み込むデータを保存する費用)
  • 分析料金(クエリを実行する際にかかる料金)

詳細については公式ドキュメントを参照
https://cloud.google.com/bigquery/pricing?hl=ja#on_demand_pricing

BigQueryにおける費用管理

Google公式ドキュメントに費用管理のベストプラクティスのページがある
https://cloud.google.com/bigquery/docs/best-practices-costs

今回はこの中から費用を抑える方法についていくつかピックアップして記載する

Google Cloudコンソール上でクエリ検証ツールを表示する

  • コンソール画面から、実行するクエリのデータ処理量を見る事ができる
    • 以下画像を例にすると、右上の「このクエリを実行すると…」という文章に処理量が表示される
    • ここで表示されるデータ処理の量をみて、実効の有無を判断する事が可能

dry run を利用する

BigQueryにはdry runの機能があり、これを利用する事でクエリを実行せずともスキャン量を確認する事が可能

bq query \
--use_legacy_sql=false \
--dry_run \
SELECT
    name,
    count
  FROM
    `babynames.names_2014`
  WHERE
    gender = 'M'
  ORDER BY
    count DESC

課金されるバイト数を制限してクエリ費用を抑える

課金されるクエリのバイト数を制限するには、課金される最大バイト数の設定を使用する。

課金される最大バイト数を設定した場合は、クエリが実行される前に、クエリで読み取られるバイト数が推定され、推定バイト数が上限を超えると、クエリが失敗し、料金は発生しない。

Google Cloud料金計算ツールを利用する

  • Google Cloudでは料金計算ツールというものを提供している
  • これを利用して、実行するクエリの種類やテーブルを設定して料金計算が可能

クラスタ化またはパーティション分割テーブルの使用

クラスタリングとパーティショニングを利用して、スキャンされるデータの量を減らす方法
パーティション分割テーブルは、コンソール画面からでも作成可能

  • テーブル作成画面の「パーティションとクラスタの設定」
  • パーティショニングフィルタやタイプを指定し、作成できる

データを日付別にパーティション分割する

※データ運用の方針による

BigQueryテーブルを日付別に分割して、テーブルをパーティショニングすることによって、関連するデータのみをクエリする方法
これにより出力までのパフォーマンスの向上とコストの削減ができる

例)
パーティション分割テーブルを照会するときに、 _PARTITIONTIME 疑似列を使用して日付または日付の範囲をフィルタ処理する

SELECT
    name,
    count
  FROM
    `babynames.names_2014`
  WHERE
    gender = 'M'
  AND
    _PARTITONETIME > `2022-12-01`
  AND
    _PARTITONETIME =< `2022-12-10`

SELECT * を避ける

クエリを実行する際に SELECT * を使用せず、必要な列のみを参照するようにする

  • 実は、BigQueryにおいて SELECT * を利用するのは最も費用のかかる方法(公式より)
    • SELECT * を使用すると、BigQueryはテーブル内のすべての列をフルスキャンしてしまうため

また、 LIMIT を使用しても読み取られるデータの量には影響しない点にも注意

監査ログを利用して、クエリのコストとBigQueryの使用状況をモニタリングする

BigQueryの課金データを表示するためのダッシュボードを作成し、それを確認しながら利用していく方法

Cloud BillingのデータをBigQueryにインポートし、Looker Studio等の可視化ツールで可視化が可能
https://cloud.google.com/billing/docs/how-to/export-data-bigquery

Discussion