はじめに
BigQuery を業務で使い始めると、「同じ集計クエリを繰り返し実行する」「ダッシュボードから定期的に同一の SUM/COUNT を叩く」といったユースケースに遭遇することがあります。BigQuery は スキャンしたバイト数に対する従量課金 であるため、集計クエリの繰り返し実行は、 コスト増に直結 します。
今回は BigQuery における ビュー(View) と マテリアライズドビュー(Materialized View, MV) について、両者の違いと使い分け、そして実際のハンズオン手順を整理してみたいと思います。
なお、Google Cloud を活用したシステム開発については、Udemy にて関連コースをリリースしておりますので、ご興味のある方はご覧ください。
1. ビューとマテリアライズドビューの違い
1-1. ビュー(標準ビュー)
ビューは、 「SELECT 文に名前を付けて保存したもの」 であり、実体としてのデータは持ちません。ビューに対するクエリは、実行のたびに 元テーブル(ベーステーブル)に対して定義済みSELECTが展開され、毎回フルにクエリが実行 されます。
- メリット:複雑なクエリを名前で再利用できる、行レベル・列レベルのアクセス制御の手段として有用、定義変更が即時反映される。
- デメリット:呼び出しの度にベーステーブルがスキャンされるため、 スキャンコストとクエリ時間の削減にはならない。
1-2. マテリアライズドビュー(MV)
マテリアライズドビューは、 ビューの定義に基づいた集計結果を、実体としてストレージに保持する仕組み です。BigQuery は MV の中身を ベーステーブルの更新に追従して自動的に再計算(増分更新)してくれます。
- メリット:事前計算済みの結果を返すため、 クエリのスキャン量・実行時間が劇的に削減される。 さらに、ユーザーが MV を直接 SELECT しなくても、ベーステーブルへのクエリを BigQuery が解析し、 MV を使った方が安いと判断すれば自動的に MV にリダイレクト(スマートチューニング) してくれる。
-
デメリット:MV 自身のストレージコストが発生する。集計関数や JOIN の使用に制約がある(例:
COUNT、SUM、MIN/MAX、APPROX_COUNT_DISTINCTなどはサポートされるが、ウィンドウ関数やLIMITなどは制限あり)。
シンプルに言えば、 「ビュー=定義の保存」「マテリアライズドビュー=結果の保存」 という違いです。同じ集計クエリを高頻度で叩くのであれば、MV を選択するのが定石です。
2. ハンズオン:ビューとマテリアライズドビューのスキャン量比較
2-1. 事前準備
Cloud Shell から、検証用データセットを作成します。(東京リージョンを想定)
export PROJECT_ID=$(gcloud config get-value project)
export REGION="asia-northeast1"
bq --location=${REGION} mk --dataset ${PROJECT_ID}:mv_handson
続いて、BigQuery Studio から100万行のサンプル売上テーブルを作成します。
CREATE TABLE mv_handson.sales AS
SELECT
n AS sale_id,
['electronics','books','food','clothing','toys'][OFFSET(CAST(FLOOR(RAND()*5) AS INT64))] AS category,
CAST(FLOOR(RAND()*100000)+100 AS INT64) AS amount,
DATE_ADD(DATE '2026-01-01', INTERVAL CAST(FLOOR(RAND()*180) AS INT64) DAY) AS sale_date
FROM UNNEST(GENERATE_ARRAY(1, 1000000)) AS n;
2-2. 標準ビューの作成
「金額が5万円超の売上を、カテゴリ別に集計する」というビューを作成します。
CREATE VIEW mv_handson.sales_by_category_view AS
SELECT category, COUNT(*) AS cnt, SUM(amount) AS total
FROM mv_handson.sales
WHERE amount > 50000
GROUP BY category;
2-3. 標準ビューのスキャン量を確認(Dry Run)
ビューに対する SELECT を実行する際、BigQuery Studio 画面上に 「このクエリを実行すると ◯◯ MB が処理されます」 と表示されます(Dry Run)。
SELECT * FROM mv_handson.sales_by_category_view;
このビューは、内部的には sales テーブル全体を都度スキャンして集計するため、スキャン量は100万行分(数十MB規模) になります。同じクエリを10回叩けば、その10倍のスキャン量=コストが発生します。
2-4. マテリアライズドビュー(MV)の作成
同じ集計を、MV として作成します。
CREATE MATERIALIZED VIEW mv_handson.sales_by_category_mv AS
SELECT category, COUNT(*) AS cnt, SUM(amount) AS total
FROM mv_handson.sales
WHERE amount > 50000
GROUP BY category;
MV の作成時、初回は集計結果が物理的に計算・格納されます。以降、sales テーブルにレコードが追加・更新されると、BigQuery が 自動的に MV の差分更新 を行います(追加コスト・運用負荷なし)。
2-5. MV のスキャン量を確認(Dry Run)
SELECT * FROM mv_handson.sales_by_category_mv;
Dry Run のスキャン量を確認すると、 MV の中身は「カテゴリ別の集計結果」のわずか数行のみ なので、スキャン量は 数KB〜数百バイトレベル まで激減します。標準ビューと比較すると、 数千分の1〜数万分の1 までコストが圧縮されることが実感できるはずです。
2-6. クリーンナップ
検証が終わったら、データセットを削除しておきます。
bq rm -r -f -d ${PROJECT_ID}:mv_handson
3. 使い分けの考え方
実務における使い分けの観点を整理すると、以下のようになります。
- 標準ビュー:複雑なJOINやサブクエリのカプセル化、行レベル・列レベルのアクセス制御、ad-hoc な分析クエリの整理用途。データの新鮮さ(リアルタイム性)を優先する場合。
- マテリアライズドビュー:BIダッシュボード、定期レポート、APIから繰り返し叩かれる集計など、「同じ集計クエリが頻繁に実行される」 ユースケース。コスト削減効果が運用コストを大きく上回る場合。
特に、Looker Studio や Tableau などの BI ツールと組み合わせる場合、ユーザー操作のたびに集計クエリが裏で走り続けるため、MV の有無で月次クエリコストが桁単位で変わることも珍しくありません。
4. おわりに
BigQuery のパフォーマンス・コスト最適化において、 マテリアライズドビューは「設定するだけで効くチューニング手段」 として費用対効果が高い機能です。一度定義してしまえば、その後のメンテナンスは BigQuery が自動で行ってくれますし、ユーザーやBIツール側のクエリを書き換える必要すらありません(スマートチューニングが自動的に MV を選択してくれるため)。
「同じ集計クエリを何度も叩いている」「ダッシュボードのレスポンスが遅い」「月次のBigQueryコストが想定より高い」と感じている方は、まずはベーステーブルに対する代表的な集計クエリを MV 化するところから着手されることをお勧めします。
プロフィール
[Maruchin Tech]
AWS、Google Cloud、製造業・SCM DXを専門とするUdemy講師・技術顧問。
新卒で日産自動車に入社。その後アクセンチュア、NTTデータを経て独立。
大手製造業の基幹システム刷新やDXプロジェクトにおいて、要件定義からアーキテクチャ設計までをリード。
現在は「現場で本当に使える技術と視点」をテーマに、エンジニア教育に従事。