BigQuery は使った分だけ払う料金体系なので小さく始めやすい一方で、1 本のクエリで思わぬ金額になることがあります。「何に対してお金がかかるのか」が分かれば、費用の大半は設計と設定で抑えられます。この記事では BigQuery の料金の仕組みを、クエリの料金 (オンデマンドと Editions)、ストレージの料金、無料枠に分けて説明し、スキャン量を減らす工夫と、使いすぎを止める上限の設定をまとめます。
料金の数字は、とくに断りがない限り 2026 年 11 月時点の Google Cloud の公式ページの米ドルの単価で、米国のロケーションのものです。単価はロケーション (東京など) によって違うので、使うロケーションの単価は公式の料金ページで確かめてください。
BigQuery の料金は「クエリ」と「ストレージ」の 2 つ
BigQuery の費用は大きく分けて次の 2 つです。
- クエリ (コンピューティング) の料金。SQL を実行して処理した分で、払い方はオンデマンドと容量ベース (Editions) の 2 種類がある
- ストレージの料金。テーブルにデータを保存している分
このほか、ストリーミングでのデータの書き込みや、BigQuery の外からデータを読み出す API などにも料金がありますが、多くのチームで費用の大半を占めるのはクエリの料金です。そのため、この記事でもクエリの料金を中心に説明します。
オンデマンド料金: スキャンしたデータ量で払う
何も設定しなければ、プロジェクトはオンデマンド料金になります。オンデマンドでは、クエリが読み込んだ (スキャンした) データ量に応じて払います。
| 項目 | 料金 (2026 年 11 月時点、公式ページより) |
|---|---|
| クエリ | 1 TiB あたり $6.25 (米国のロケーション) |
| 無料枠 | 毎月最初の 1 TiB まで無料 |
課金のされ方には、知っておきたい細かな決まりがあります。
- 1 つのクエリにつき最低 10 MB、参照するテーブル 1 つにつき最低 10 MB が課金される。小さなテーブルを何度もクエリしても、0 にはならない
- 結果がキャッシュから返されたクエリと、エラーになったクエリには課金されない
- 実行にかかった時間ではなく、読み込んだデータ量で決まる
BigQuery はデータを列ごとに保存しているので、読み込むのはクエリで使った列だけです。逆に言えば、テーブルの行数が多くても、使う列を絞れば読み込む量は減ります。ここが費用を抑えるときの出発点になります。
LIMIT では読み込む量は減らない
よくある誤解が LIMIT です。公式ドキュメントにあるとおり、クラスタリングしていないテーブルに SELECT * ... LIMIT 10 を実行しても、読み込む量はテーブル全体の量のままです。返ってくる行が 10 行でも、全列・全行を読んだ分が課金されます。中身を少し見たいだけなら、後で説明するプレビューを使います。
容量ベース (Editions): 処理能力を時間で借りる
もう 1 つの払い方が容量ベースで、BigQuery Editions と呼ばれます。読み込んだデータ量ではなく、クエリを処理する能力を「スロット」という単位で確保し、使った時間 (スロット時間) で払います。スロットは、BigQuery がクエリを実行するための仮想的な計算の単位です。
Editions には 3 つの種類があります。
| エディション | 従量の単価 (スロット時間あたり) | 主な違い |
|---|---|---|
| Standard | $0.04 | 自動スケーリングのみ。予約の上限は 1,600 スロット。期間の契約はなし。BigQuery ML は使えない |
| Enterprise | $0.06 | 自動スケーリングに加えて、常に確保しておく分 (ベースライン) を持てる。BigQuery ML、BI Engine、顧客管理の暗号鍵などに対応 |
| Enterprise Plus | $0.10 | Enterprise の機能に加えて、災害対策の機能や、規制に対応するための管理機能 |
単価は 2026 年 11 月時点の公式の料金ページの、従量 (pay as you go) の米国の例です。Enterprise と Enterprise Plus には 1 年と 3 年の契約があり、契約すると単価が下がります。
自動スケーリングでは、負荷に応じてスロットが増減し、使った分が課金されます。既定では課金に 1 分の最小単位があります。
Editions とオンデマンドはプロジェクトごとに選べます。たとえば、定期的に重い集計を回すプロジェクトは Editions に、たまにしかクエリを打たないプロジェクトはオンデマンドのままに、という使い分けができます。
オンデマンドと Editions のどちらが安いか
どちらが安いかは、読み込む量と、スロットを使う時間で決まります。ざっくりした目安を計算してみます。
Standard で 100 スロットを 1 か月 (約 730 時間) ずっと使うと、$0.04 × 100 × 730 = 約 $2,920 です。オンデマンドで同じ金額になるのは、$2,920 ÷ $6.25 = 約 467 TiB を読み込んだときです。実際には自動スケーリングで使わない時間は課金されないので、Editions の費用はこれより小さくなることも多く、逆にクエリが重ければ 100 スロットでは足りないこともあります。
判断の手がかりとして、次のように考えると整理しやすくなります。
- 月に読み込む量が無料枠の 1 TiB 前後から数 TiB 程度なら、オンデマンドで十分なことが多い
- 毎月の請求が大きく、読み込む量の割に計算が軽いクエリ (大きなテーブルを単純に集計するなど) が多いなら、Editions を試算する価値がある
- 費用の上限を読みやすくしたいなら、Editions で自動スケーリングの上限を決めておく方法もある
実際の判断は、過去のクエリのスロットの使用量 (後で紹介する INFORMATION_SCHEMA.JOBS の total_slot_ms) をもとに試算するのが確実です。
ストレージの料金と無料枠
ストレージは保存しているデータの量で課金されます。データを変更していない期間で「アクティブ」と「長期」に分かれ、課金のしかたで「論理」と「物理」に分かれます。
| 種類 | 1 GiB・月あたり (us-central1 の例) |
|---|---|
| アクティブな論理ストレージ | $0.02 |
| 長期の論理ストレージ | $0.01 |
| アクティブな物理ストレージ | $0.04 |
| 長期の物理ストレージ | $0.02 |
単価は公式ドキュメントの INFORMATION_SCHEMA.TABLE_STORAGE の説明にある us-central1 の例です。毎月 10 GiB までは無料です。
テーブル (パーティション分割テーブルならパーティションごと) が 90 日続けて変更されないと、自動で長期ストレージの単価になり、およそ半額になります。データを変更すると、90 日の数え直しになります。
論理と物理の違いは、何のサイズで数えるかです。論理ストレージは圧縮前のサイズで数え、タイムトラベル (過去の状態に戻すための履歴) の分は単価に含まれます。物理ストレージは圧縮後のサイズで数え、タイムトラベルなどの分は別に数えます。圧縮が効きやすいデータなら物理のほうが安くなることがあり、データセットごとに選べます。逆に、テーブルを何度も丸ごと上書きすると、物理ではタイムトラベルの分が増えやすくなります。
ストレージで手軽にできる節約は、いらないテーブルを残さないことです。作業用のデータセットには、テーブルの既定の有効期限を設定しておくと、作ったテーブルが自動で消えます。
-- tmp データセットに作ったテーブルを 7 日で自動削除する
ALTER SCHEMA tmp
SET OPTIONS (default_table_expiration_days = 7);
無料枠をまとめると、クエリが毎月 1 TiB、ストレージが毎月 10 GiB です。小さな分析や試作なら、この範囲に収まることもあります。
スキャン量を減らす工夫
オンデマンドの費用は読み込む量にほぼ比例します。読み込む量を減らす方法を、効果の大きい順に紹介します。
1. 必要な列だけを SELECT する
いちばん簡単で効果の大きい方法です。BigQuery は列ごとに読み込むので、SELECT * をやめて必要な列だけを書けば、その分だけ読み込む量が減ります。大半の列が必要で、一部だけ要らないときは SELECT * EXCEPT が使えます。
-- 全列を読む (重い)
SELECT * FROM shop.events WHERE DATE(event_time) = '2026-10-31';
-- 必要な列だけを読む
SELECT user_id, event_name, event_time
FROM shop.events
WHERE DATE(event_time) = '2026-10-31';
-- 大きな列だけを除く
SELECT * EXCEPT (payload)
FROM shop.events
WHERE DATE(event_time) = '2026-10-31';
2. パーティションで読み込む範囲を日付で絞る
パーティション分割テーブルはテーブルを日付などで区切って保存します。WHERE でパーティションの列を絞り込むと、該当するパーティションだけが読み込まれます。ログやイベントのように日付で増えていくテーブルでは、効果が大きい方法です。
パーティションの列で絞り込まないクエリを禁止するオプション require_partition_filter もあります。うっかり全期間を読むクエリを防げます。
CREATE TABLE shop.events (
event_time TIMESTAMP,
user_id STRING,
event_name STRING,
payload JSON
)
PARTITION BY DATE(event_time)
CLUSTER BY user_id, event_name
OPTIONS (
require_partition_filter = TRUE
);
このテーブルに、event_time の条件がないクエリを実行するとエラーになります。
3. クラスタリングでよく絞り込む列をまとめる
上の例の CLUSTER BY がクラスタリングです。指定した列 (最大 4 つ) の値でデータを並べて保存するので、その列で絞り込むと、関係のないブロックを読まずに済みます。読まなかったブロックは課金されません。
ただし、クラスタリングの効果は実行してみるまで分からないので、実行前の見積もりは実際より大きな値 (上限) になります。公式ドキュメントでは、実行前に費用をきちんと見積もりたいならパーティション、と使い分けが説明されています。日付でパーティションを切り、よく WHERE に使う列 (ユーザー ID、ステータスなど) でクラスタリングする組み合わせがよく使われます。
4. 中身を見るときはプレビューを使う
テーブルの中身を少し見たいだけなら、Google Cloud コンソールのテーブルの「プレビュー」を使います。プレビューは無料で、割り当て (クォータ) も消費しません。bq コマンドなら bq head でも同じように見られます。
bq head --max_rows=10 shop.events
5. 実行前に読み込む量を確かめる
コンソールのクエリエディタでは、SQL を書くと、実行したときに処理されるデータ量が右上に表示されます。bq コマンドなら --dry_run をつけると、実行せずに読み込む量だけを確かめられます。
bq query --use_legacy_sql=false --dry_run \
'SELECT user_id, event_name FROM shop.events WHERE DATE(event_time) = "2026-10-31"'
6. 何度も使う途中の結果はテーブルに保存する
同じ大きなテーブルから、何段階にも分けて集計する処理では、途中の結果をテーブルに保存しておき、次の段階ではその小さなテーブルを読むようにします。毎回もとの大きなテーブルを読むより、読み込む量を減らせます。
使いすぎを止める上限の設定
工夫をしても、ミスや想定外のクエリは起こります。費用の上限は、3 つの段階で設定できます。
クエリごとの上限: 最大課金バイト数
クエリごとに「これ以上読むなら実行しない」という上限を指定できます。見積もりが上限を超えたクエリは、課金されずに失敗します。
# 100 GB (107374182400 バイト) を超えるクエリは実行しない
bq query --use_legacy_sql=false --maximum_bytes_billed=107374182400 \
'SELECT ...'
コンソールでは、クエリの設定の「最大課金バイト数」で指定できます。アプリケーションやスケジュールされたクエリからも、ジョブの設定で同じ値を渡せます。
1 日あたりの上限: カスタム割り当て
プロジェクト全体、またはユーザーごとに、1 日に読み込める量の上限を設定できます。設定するのは、コンソールの「IAM と管理」→「割り当てとシステム上限」で、BigQuery API の「Query usage per day」(プロジェクト単位) と「Query usage per day per user」(ユーザー単位) です。値は TiB で指定します。
上限に達すると、その日はクエリが quotaExceeded のエラーになります。プロジェクト単位の上限に達すると、プロジェクトの全員がクエリを実行できなくなるので、業務への影響を考えて値を決めます。この割り当てはオンデマンドのクエリにだけ効きます。
月の予算: Cloud Billing の予算とアラート
Cloud Billing では、月の予算を決め、50%、90%、100% のように使った割合で通知を送れます。予算アラートは通知するだけで、クエリは止まりません。止める役割はカスタム割り当てに、気づく役割は予算アラートに、と分けて設定します。
費用の大きいクエリを探す
すでに請求が大きくなっている場合は、どのクエリが多く読み込んでいるかを探します。INFORMATION_SCHEMA.JOBS に、実行したジョブの記録が残っています。
SELECT
user_email,
LEFT(query, 120) AS query_head,
ROUND(total_bytes_billed / POW(1024, 4), 3) AS tib_billed,
ROUND(total_slot_ms / 1000 / 3600, 1) AS slot_hours,
creation_time
FROM `region-us`.INFORMATION_SCHEMA.JOBS
WHERE creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
AND job_type = 'QUERY'
ORDER BY total_bytes_billed DESC
LIMIT 20;
region-us の部分はデータセットのあるロケーションに合わせます (東京なら region-asia-northeast1)。tib_billed の大きい順に並ぶので、上位のクエリから、列の絞り込みやパーティションの条件が足りているかを見直します。同じクエリが何度も実行されている場合は、ダッシュボードの自動更新やスケジュールの設定も確かめます。なお、INFORMATION_SCHEMA へのクエリにも、オンデマンドでは最低 10 MB の料金がかかります。
費用の変化に気づくには
ここまでの設定をしておけば、大きな事故は防ぎやすくなります。それでも、ダッシュボードの設定が変わった、新しいバッチが毎時全期間を読み始めた、といった変化は、月末の請求で初めて気づくことがあります。上の INFORMATION_SCHEMA.JOBS のクエリを週に 1 回見る、スケジュールされたクエリで 1 日の読み込み量を集計して通知する、といった仕組みがあると、早めに気づけます。
BigQuery に入っている業務データの変化を見張りたい場合は、AI に任せる方法もあります。Scandock は BigQuery に対応したデータベースの監視サービスで、AI がテーブルの構成と実データを読んで、売上や注文数など何を監視するかと、取得と判定の間隔を決めます。値の推移を踏まえて異常かどうかを判断し、異常のときは読み取り専用のクエリで関連するデータを調べて、根拠と対処案をつけて通知します。DB に詳しくない人でも、チャットで「先週から注文が減っていないか」と聞くと、AI が調べてグラフつきで答えます。