ざっくりGCP料金計算

BigQueryで月100万円の請求が来た日のこと

パーティション設定を忘れただけで、翌月の請求書が地獄になった実話。

「なんか先月より請求、高くない?」

それは社内のバックオフィス担当者からのSlackメッセージで始まった。「GCPの請求、先月の10倍来てるんだけど大丈夫?」。最初は誤読だと思った。10倍なわけがない。でも請求書を開くと、本当に10倍だった。前月が約10万円、今月が約100万円。画面をスクロールしながら、少しの間思考が止まった。

原因はパーティション未設定のBigQueryテーブル

原因はBigQueryだった。新しいデータ分析基盤を立ち上げたばかりで、とにかく動くことを優先してリリースした。ログデータをGCSからBigQueryに日次でロードして、社内向けのダッシュボードからクエリが走る仕組みを作り、「よし、完成」とリリースした。そこまでは良かった。

問題は、そのテーブルにパーティションを設定していなかったことだ。ログデータなので毎日数GBずつ追加されていく。パーティションを切っていないのでクエリを1本投げるたびにテーブルの全期間分をフルスキャンする。ダッシュボードにはウィジェットが10個あり、ページを開くたびに10本のクエリが一斉に走る。そのダッシュボードを社員が1日に何度も開く。

計算してみると恐ろしかった。稼働3ヶ月でテーブルサイズは約500GBに達していた。BigQueryのオンデマンド課金は$6.25/TB。1クエリで500GBをスキャンすると$3.125かかる。それが1日100回走ると$312.5/日。1ヶ月で約$9,375、円換算で100万円を超えた。ダッシュボードを開くたびに1,000円近く課金されていた計算になる。

対処と、やり直せるならこうした

対処はシンプルだった。テーブルを日付カラムでパーティション分割し直し、クエリのWHERE句に必ず日付条件を含めるルールを設けた。それだけで1クエリあたりのスキャン量が当日分のみに絞られ、翌月の請求は元の水準に戻った。

ただし既存のテーブルにパーティションを後から追加するには、新しいテーブルを作ってデータを移し替える必要がある。データ量が多ければその移行作業自体にもクエリ費用が発生する。最初からパーティション設計をしておくべきだったという教訓は実感を伴ってのものだ。

もう一つの教訓はコスト監視の粒度だ。Cloud Billing全体で眺めているだけでは、どのクエリが費用を爆発させているか分からない。INFORMATION_SCHEMA.JOBS_BY_PROJECTというビューを使えば、直近のクエリごとのスキャン量とコストを確認できる。これを週次で確認する習慣があれば、月末の請求書を見て初めて気づく事態は防げた。この件は社内で稟議書を書くことになり、「なぜ想定外の費用が発生したのか」「再発防止策は何か」を役員に説明することになった。費用の問題は技術的な問題であると同時に、組織的な問題でもある。そのことを痛感した出来事だった。