はじめに:BQは無料枠(毎月クエリ1TB・ストレージ一定量)で十分戦えるという話
「BigQuery(以下BQ)を使ってみたいけど、クラウドの従量課金がこわい」——小規模EC事業者さんや個人事業主さんから、よくいただく相談です。
結論から言うと、月の注文が数百〜数千件くらいの規模であれば、BigQueryは無料枠の範囲内でも十分にデータ分析の基盤として戦えます。むしろ「無料枠に収める」ことを前提に設計すると、自然とムダのないクリーンなデータ基盤になっていく、というおまけまでついてきます。
この記事では、BQを無料枠内で運用し続けるための設計戦略を、小規模事業者の目線でまとめます。専門用語はなるべくかみ砕いて説明していきますね。
この記事の前提 本記事で触れる無料枠の数値(クエリ量・ストレージ量など)は、執筆時点での一般的な「目安」です。Googleの料金体系は予告なく変わることがあるため、実際の運用前には必ず公式ドキュメントで最新の情報を確認してください。
無料枠の中身をざっくり把握する
まず、BQの無料枠がどういう構造になっているかを押さえましょう。BQの課金は大きく「クエリ(計算)」と「ストレージ(保管)」の2つに分かれていて、それぞれに無料の枠が設けられています。
| 項目 | 無料枠の目安 | ひとことメモ |
|---|---|---|
| クエリ(オンデマンド) | 毎月 1TB スキャンまで無料 | 「読み込んだデータ量」で課金される |
| ストレージ | 一定量(10GB程度)まで無料 | テーブルに保管しているデータ量 |
ここで大事なのは、クエリの課金が「実行回数」でも「結果の行数」でもなく、スキャン(読み込み)したデータ量で決まるという点です。つまり、1回のクエリで巨大なテーブルを丸ごと読むと一気に枠を消費し、逆に必要な部分だけ読めばほとんど消費しません。
覚えておきたい一文 「課金されるのは、読み込んだ量。出力した量ではない。」 この感覚を持っておくだけで、設計の判断がぐっと楽になります。
繰り返しになりますが、ここで挙げた「1TB」「10GB」といった数字はあくまで目安です。最新の正確な値は公式の料金ページでご確認ください。
無料枠内に収める設計戦略
ここからが本題です。小規模ECのデータ量であれば、いくつかの基本を押さえるだけで、無料枠を超えずに運用を続けられます。
戦略1:スキャン量を減らす(SELECT * をやめる)
一番効果が大きく、一番手軽なのがこれです。BQは列指向といって、列ごとにデータを保管しています。そのため「全列を読む SELECT *」は、必要のない列まで全部読み込んでしまい、スキャン量がふくらみます。
-- NG:全列を読んでしまう
SELECT * FROM orders;
-- OK:必要な列だけ読む
SELECT order_id, order_date, total_amount FROM orders;
たとえば「日別の売上合計が知りたい」だけなら、注文日と金額の2列があれば足ります。商品名や住所まで読む必要はありません。この一手だけで、スキャン量が何分の一にもなることは珍しくありません。
戦略2:パーティションで「読む範囲」を区切る
パーティション分割は、テーブルを日付などのキーで内部的に区切っておく仕組みです。注文日でパーティションを切っておけば、「直近30日だけ集計したい」というときに、その期間のデータだけをスキャンできます。
-- 注文日でパーティション分割したテーブルを作る例
CREATE TABLE shop.orders (
order_id STRING,
order_date DATE,
total_amount NUMERIC
)
PARTITION BY order_date;
集計するときは、パーティションキー(この例では order_date)で必ず範囲を絞るのがコツです。
-- 直近30日だけをスキャンする
SELECT order_date, SUM(total_amount) AS sales
FROM shop.orders
WHERE order_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY order_date;
WHERE句でパーティションを絞らないと、結局テーブル全体を読んでしまうので注意してください。せっかく区切ったのに範囲指定を忘れる、というのはありがちなミスです。
戦略3:中間集計テーブルを作る
毎回、生の注文データ(数万行・数十万行)を集計し直すのはもったいないです。よく使う集計結果は、あらかじめ小さなテーブルにまとめておきましょう。
たとえば「日別売上サマリー」を1日1回つくっておけば、ダッシュボードやレポートはその小さなテーブルを読むだけで済みます。元データが大きくても、参照するのは集計後の軽いテーブルなので、スキャン量を大幅に節約できます。
-- 日別サマリーを作っておく(1日1回更新するイメージ)
CREATE OR REPLACE TABLE shop.daily_sales AS
SELECT
order_date,
COUNT(*) AS order_count,
SUM(total_amount) AS sales
FROM shop.orders
GROUP BY order_date;
「重い集計は1回だけ、参照は何度でも軽く」——この役割分担が、無料枠運用の肝です。
戦略4:保持期間と有効期限を決める
ECデータは放っておくとどんどん溜まります。「いつまでのデータを、どこまで持つか」をあらかじめ決めておくと、ストレージも安定します。
- パーティションごとに有効期限(パーティション有効期限)を設定し、古いデータを自動で消す
- テーブル自体に有効期限を設定する(一時テーブルや検証用テーブルに便利)
「直近2年分の明細だけ生データで持ち、それ以前は月次サマリーだけ残す」といったルールにすると、ストレージは頭打ちになり、無料枠内で安定して回せます。
戦略5:不要データは思い切って消す
検証用に作ったテーブル、途中でやめた集計、コピーして放置したテーブル——こうした「使っていないデータ」は、知らないうちにストレージを圧迫します。
定期的に棚卸しをして、不要なテーブルは削除しましょう。ただし削除は取り消せない操作なので、消す前に「本当に使っていないか」をひと呼吸おいて確認してくださいね。大事なテーブルを誤って消すと元に戻せません。
設計戦略のまとめ
- SELECT * をやめて必要な列だけ読む
- パーティションで読む範囲を区切る
- よく使う集計は中間テーブルにまとめる
- 保持期間・有効期限を決める
- 不要データは(慎重に)削除する
監視:使用量を見て枠内に保つ
設計を整えたら、最後は「ちゃんと枠内に収まっているか」を確認する習慣です。気づかないうちに枠を超えていた、という事態を防ぎます。
実行前にスキャン量を見積もる
BQには、クエリを実際に走らせる前に「このクエリは何バイト読みそうか」を見積もるドライランという機能があります。重そうなクエリを書いたときは、実行前にチェックすると安心です。
# bq コマンドラインツールでドライラン(課金なしで見積もり)
bq query --use_legacy_sql=false --dry_run \
'SELECT order_date, SUM(total_amount) FROM shop.orders GROUP BY order_date'
「このクエリは○○バイト処理します」と表示され、実際の課金やスキャンは発生しません。
月の使用量を定期的に確認する
GCPのコンソールでは、月のクエリ処理量やストレージ量を確認できます。月初や週初めに一度ながめておくだけでも、「今月は少しペースが速いな」といった気づきが得られます。
不安な場合は、予算アラート(一定額に近づいたら通知が来る仕組み)を設定しておくと、想定外の課金を早めに察知できます。小規模運用なら、無料枠を超えてもいきなり大きな額になることは多くありませんが、「気づける状態」を作っておくと精神的に安心です。
| タイミング | やること |
|---|---|
| クエリを書いたとき | ドライランでスキャン量を見積もる |
| 週に1回 | 月の累計スキャン量をざっと確認 |
| 月に1回 | ストレージの棚卸し・不要テーブル整理 |
まとめ:小さく始めて困ったら拡張
BigQueryは「大企業のための重厚なツール」というイメージを持たれがちですが、小規模ECのデータ量であれば、無料枠の範囲内で十分に実用的なデータ基盤を組めます。
ポイントを振り返ります。
- 課金されるのは「読み込んだ量」。だから必要な列・必要な範囲だけ読む
- パーティションと中間集計テーブルでスキャン量を構造的に抑える
- 保持期間と有効期限を決め、不要データは慎重に削除する
- ドライランと使用量チェックで、枠内に収まっているかを見守る
まずは小さく始めて、事業が伸びてデータ量が増え、無料枠では足りなくなってきたら、そのときに有料の範囲へ拡張すればよいのです。最初から大きく構える必要はありません。「困ったら拡張」で十分間に合います。
なお、本記事で触れた無料枠の数値はあくまで執筆時点での目安です。実際に運用を始める前には、Googleの公式ドキュメントで最新の料金・無料枠を必ず確認してください。