BigQuery のコスト管理方法を調べてみた
こんにちは、みかみです。
テーブルやインデックスチューニング不要で大量データでも十分な処理速度が確保できるという便利な BigQuery ですが、知らないうちにすごいお金かかったりしていないか、やはりいまだにちょっと心配。。
やりたいこと
BigQuery では、ストレージ使用量と SQL クエリの処理データ量に対して課金が発生します。
保存が必要なデータの精査や処理内容の検討、SQL クエリのチューニングなどでもコストの最適化が見込めますが、その他、BigQuery の利用料金を気を付けるには、どんな方法があるのか確認したい。
クエリ実行前に --dry_run で処理データ量を確認
--dry_run オプションで、実際にクエリを実行すると処理データ量はどのくらいになるのかを事前に確認することができます。
- ストレージとクエリの費用の見積もり | BigQuery ドキュメント
- クエリのドライランの実行 | BigQuery ドキュメント
- BigQuery のおすすめの方法: 費用を抑える > ドライランの実行 | BigQuery ドキュメント
まずは CLI で実行してみます。
(test_bq) [ec2-user@ip-10-0-43-239 ~]$ bq query --dry_run --use_legacy_sql=false < test_cost.sql Query successfully validated. Assuming the tables are not modified, running this query will process 65935918 bytes of data.
処理バイト数が確認できました。
また、クライアントライブラリを使ってプログラムから SQL 実行する場合でも、同様に dry run の指定ができます。
ドキュメントに記載のあった Python コードのサンプルを実行してみます。
from google.cloud import bigquery client = bigquery.Client() job_config = bigquery.QueryJobConfig(dry_run=True, use_query_cache=False) query_job = client.query( ( "SELECT name, COUNT(*) as name_count " "FROM `bigquery-public-data.usa_names.usa_1910_2013` " "WHERE state = 'WA' " "GROUP BY name" ), job_config=job_config, ) print("This query will process {} bytes.".format(query_job.total_bytes_processed))
(test_bq) [ec2-user@ip-10-0-43-239 ~]$ python test_dry_run.py This query will process 65935918 bytes.
CLI 実行時同様、処理データ量が取得できました。
必要ならば、dry run 結果を見てデータ量が大きい場合はアラートを上げて処理中断する、などのプログラム実装も簡単にできそうです。
料金計算ツールで利用額を見積もり
dry run でデータ量は確認できますが、じゃあ、それ、いくらなの?
あと、クエリ料金とは別に課金されるストレージ使用料って、今いくら?
という時には、WebUI 画面の料金計算ツールで確認できます。
なお、ストレージ使用量は、管理画面からテーブル毎のデータサイズを確認できますが、
SQL でデータセット全体のストレージ使用量も取得できます。
Google Cloud Platform 料金計算ツールでそれぞれのデータ量を入力すれば、課金額が算出できます。
クエリの課金バイト数を制限しておく
GCP 管理コンソール BigQuery 画面の「その他」ボタン「クエリの設定」から、
詳細オプションで「課金される最大バイト数」を指定できます。
試しに、上限を 1byte に設定して SQL を実行してみると
ちゃんとエラーになりました。
設定値を超えるクエリは実行したとしてもエラーになるので、うっかりミスを防ぐことができそうです。
まとめ(所感)
一時期話題に上がるほどの事故が発生したこともある BigQuery 利用コストですが、さすが、管理機能もドキュメントも充実していると思いました。
特に SQL 実行時の課金上限の設定は、安心して BigQuery を使うことができる便利な機能だと思います。 私もうっかり失敗しないように、上限設定しておこうと思いました。