Google Cloud ハンズオン教科書|2026-08 版
第 11 章 試験ガイド 1.3 試験ガイド 2.2

データ分析基盤 — BigQuery・Pub/Sub・Dataflow

サーバーレス DWH とストリーミング。データが流れる道を設計する

この章で学ぶこと

試験ガイド対応: セクション 1.3(ネットワーク、ストレージ、コンピューティング リソースの設計)、2.2(ストレージ システムの構成)

データが流れる道 — 分析基盤の全体像

第 8 章から第 10 章まではデータを「置く・捌く」プロダクトを見てきました。本章はそのデータを「分析する」側、つまりデータ分析基盤です。Google Cloud の分析基盤は、収集(Pub/Sub)→ 処理(Dataflow)→ 保存・分析(BigQuery)→ 可視化(Looker Studio など)という 4 段のパイプラインが基本形で、公式ドキュメントでも ETL / BI の代表構成としてこの並びが示されています。まず全体の地図を頭に入れましょう。

アプリ / IoT デバイス メッセージを publish Pub/Sub(収集) トピック / サブスクリプション サブスクリプションから読み取り Dataflow(変換・集計) Apache Beam / 自動スケーリング Cloud Storage バッチファイル バッチ読み取り ストリーミング書き込み BigQuery(保存・分析) サーバーレス DWH 変換不要なら BigQuery サブスクリプションで直行 SQL / ダッシュボード Looker Studio(可視化) BI・可視化
図 11-1 ストリーミング分析の標準パイプライン。リアルタイムのイベントは Pub/Sub で受け、Cloud Storage 上のファイルはバッチとして Dataflow が読む。変換が要らないなら点線の BigQuery サブスクリプションで Pub/Sub から BigQuery に直接書ける(ハンズオン 11-3 で体験)。
段階プロダクト役割
収集Pub/Subイベントを受け止めるバッファ。送信側と受信側を疎結合にし、スパイクを吸収する
処理DataflowApache Beam パイプラインでバッチ / ストリーミングを同じコードで変換・集計する
保存・分析BigQueryサーバーレスのデータウェアハウス(DWH)。SQL でペタバイト級を分析する
可視化・活用Looker Studio ほかダッシュボード・BI。BigQuery ML や Gemini Enterprise Agent Platform(旧称 Vertex AI)へつなげば ML にも使える

BigQuery — サーバーレスデータウェアハウス

アーキテクチャ: ストレージとコンピュートの分離

BigQuery はフルマネージド・サーバーレスのデータウェアハウスです。インスタンスのプロビジョニングもスケール操作も不要で、SQL(GoogleSQL)を投げるとその場で必要な計算資源が割り当てられます。設計の核心はストレージ層とコンピュート層の分離です。データは列指向フォーマットで専用ストレージに保存され、クエリ実行時だけスロット(クエリ実行の計算単位。仮想 CPU)が割り当てられて、両層をペタビット級の内部ネットワークが結びます。読み書きと分析が同じリソースを取り合う従来型 DB のボトルネックがなく、ストレージとコンピュートを独立にスケール・課金できるのがポイントです。

SQL クエリ(コンソール / bq / API) スロットに割り当て コンピュート層 — スロット(仮想 CPU) スロット スロット スロット スロット ペタビット級ネットワークで読み書き ストレージ層 — 列指向フォーマット データセット / テーブル タイムトラベル(既定 7 日) 独立に スケール 独立に スケール
図 11-2 BigQuery のストレージ・コンピュート分離。クエリのたびにスロットが割り当てられ、列指向ストレージから必要な列だけを読む。課金もこの構造どおり「スキャンした量(または確保したスロット)」と「保存量」に分かれる。

データはプロジェクト → データセット → テーブル / ビューの階層で管理します。データセットにはロケーション(asia-northeast1 や US マルチリージョンなど)があり、作成後は変更できません。操作はコンソール・bq CLI・REST API・各言語のクライアントライブラリ・ODBC / JDBC ドライバから行えます。取り込みは Avro / Parquet / CSV / JSON などのバッチ読み込み(課金対象外の無料オペレーション)と、Storage Write API によるストリーミング挿入の 2 系統が基本です。分析側の拡張として、SQL だけで機械学習モデルを作る BigQuery ML、外部データを扱う BigLake・外部テーブル・フェデレーテッドクエリも用意されています。

パーティショニングとクラスタリング — スキャン量を設計する

BigQuery のオンデマンド課金は「クエリがスキャンしたバイト数」で決まるため、スキャン量を減らす設計 = 性能とコストの設計です。道具は 2 つあります。

パーティショニングはテーブルを区画(パーティション)に物理分割し、フィルタに合致する区画だけをスキャンさせる仕組みです(プルーニング)。種類は 3 つ — ① DATE / TIMESTAMP / DATETIME 列による時間単位パーティショニング(粒度は時間 / 日 / 月 / 年。日次が既定で最もよく使う)、② 取り込み時刻で自動分割する取り込み時間パーティショニング(疑似列 _PARTITIONTIME で参照)、③ 整数列の範囲で分割する整数範囲パーティショニングです。

クラスタリングは指定した列(最大 4 列。指定順に効く)の値でストレージブロックをソート・同居配置し、フィルタや集計に関係するブロックだけを読ませる仕組みです。高カーディナリティ(値の種類が多い)列に強く、追加データの再クラスタリングはバックグラウンドで自動・無料で行われます。両者は併用でき、「日付でパーティション → 区画内をユーザー ID でクラスタリング」が定番です。

クエリ SELECT ... WHERE dt = '08-15' AND user_id = 'u42' プルーニング 日単位パーティション分割テーブル dt=08-14 スキップ dt=08-15 u00〜u19 u20〜u39 u40〜u59 u60〜u99 user_id でソート dt=08-16 スキップ
図 11-3 プルーニングの 2 段構え。日付フィルタで真ん中のパーティションだけが残り、その中もクラスタ列(user_id)でソート済みなので「u40〜u59」のブロックしか読まれない。スキャン量が課金額に直結する BigQuery では、この図がそのままコスト削減の仕組みになる。
観点パーティショニングクラスタリング
仕組み区画への物理分割(プルーニング)ブロックのソート・同居配置
列数1 列(+ 取り込み時間)最大 4 列(指定順に効く)
コスト見積り実行前に正確に分かる実行後にしか確定しない
向く場面単一列(主に日付)の範囲フィルタ、厳密なコスト管理高カーディナリティ列、複数列でのフィルタ・集計
目安1 パーティション 10 GB 以上が目安テーブル 64 MB 以上で効果。併用が定番

料金モデルとコスト制御

クエリ(コンピュート)の課金は 2 モデルから選びます(2026-08 時点)。

ストレージは月あたり最初の 10 GiB が無料で、90 日間変更のないテーブルは自動的に約 50% 割引の長期保存料金になります。バッチ読み込み・テーブル削除などは無料オペレーションです。学習用にはBigQuery サンドボックスもあり、クレジットカードなし・無料枠(ストレージ 10 GiB / クエリ月 1 TiB)だけで試せます(テーブルは 60 日で自動失効。ストリーミングや DML は使えません)。

コスト暴走を防ぐ道具は覚える価値があります。実行前にスキャン量を確認する bq query --dry_run、上限を超えるクエリを実行前に拒否する --maximum_bytes_billed、プロジェクト / ユーザー単位で 1 日のスキャン量を制限するカスタムクォータ、そして中身を眺めるだけなら課金されないプレビュー(bq head)です。

試験の視点: 「ペタバイト級のデータを SQL で、インフラ運用なしで分析したい」→ BigQuery が第一候補です。料金モデルは「使った分だけ / 散発的」→ オンデマンド、「毎月のコストを予測可能にしたい / 常時大量」→ 容量ベース(エディション)と読み替えます。「特定チームのクエリで請求が急増した。防ぎたい」ならカスタムクォータや maximum_bytes_billed、「日付範囲の分析クエリが高い・遅い」ならパーティショニング + クラスタリングが答えの軸になります。第 17 章で扱う請求データの BigQuery エクスポートも頻出のセットです。

Pub/Sub — 非同期メッセージング

トピックとサブスクリプション

Pub/Sub は非同期・スケーラブルなメッセージングサービスです。メッセージを送るパブリッシャーはトピックに publish し、受け取るサブスクライバーはサブスクリプション経由でメッセージを受信します。送信側は受信側が誰か・生きているかを知る必要がなく、コンポーネントの疎結合化とトラフィックスパイクの吸収がこのサービスの存在意義です。1 つのトピックに複数のサブスクリプションを付ければ、同じメッセージを複数システムがそれぞれのペースで処理できます。配信レイテンシは典型的には 100 ミリ秒程度で、リアルタイム分析・イベント駆動アーキテクチャ(第 7 章の Eventarc / Cloud Run functions)・IoT テレメトリの受け口として使われます。

配信保証は既定で at-least-once(少なくとも 1 回)、順序保証なしです。つまり同じメッセージが 2 回届くことがある前提で、受信処理は冪等に作ります。サブスクリプションの受信方式は次から選びます。

方式動き向く場面
pullサブスクライバーが自分のペースで取りに行くスループット重視のワーカー、Dataflow などの基盤
pushPub/Sub が HTTPS エンドポイントへ POST するCloud Run などの Web サービスに配る
エクスポート(BigQuery)サブスクライバー不要で BigQuery テーブルへ直接書き込む変換なしのストリーミング取り込み(ハンズオン 11-3)
エクスポート(Cloud Storage)オブジェクトとして Cloud Storage へ書き出すアーカイブ・バッチ連携

確認応答・再配信・デッドレター

受信したメッセージは処理完了後に確認応答(ack)を返します。ack が ack 期限(既定 10 秒、10〜600 秒で設定可能)内に返らなければ、Pub/Sub はそのメッセージを再配信します。未 ack のメッセージはメッセージ保持期間(既定 7 日、10 分〜31 日)の間残り続けます。またサブスクリプション自体にも有効期限があり、既定ではサブスクライバーの活動が 31 日間ないと自動削除されます(無期限にも設定可能)。

処理が恒久的に失敗するメッセージ(不正なフォーマットなど)を放置すると再配信が無限に続くため、デッドレタートピックを設定します。配信試行回数が max-delivery-attempts(5〜100 回、既定 5 回)を超えたメッセージは別トピックへ隔離され、後から調査・再処理できます。設定時は Pub/Sub のサービスアカウント(service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com)に、デッドレタートピックへの roles/pubsub.publisher と元サブスクリプションへの roles/pubsub.subscriber を付与する必要があります。

パブリッシャー publish トピック 配信 サブスクリプション メッセージ保持 7 日 pull / push 配信 ack(確認応答) サブスクライバー 受信して処理 期限超過で 再配信 最大配信試行回数を超過 デッドレタートピック 調査・再処理用に隔離 ※ デッドレター側にも回収用サブスクリプションを必ず作る
図 11-4 メッセージのライフサイクル。ack が期限(既定 10 秒)内に返らないと右のループで再配信され、試行回数が上限(既定 5 回)を超えると左下のデッドレタートピックへ移る。サブスクリプションのないトピックに届いたメッセージは失われるため、デッドレタートピックにも回収用サブスクリプションが必須。

順序指定と exactly-once

既定の Pub/Sub は順序を保証しませんが、メッセージに順序指定キー(ordering key)を付け、サブスクリプションで --enable-message-ordering を有効にすると、同一キー・同一リージョンで publish されたメッセージは publish 順に配信されます。代償として順序指定キーごとのスループットは 1 MBps に制限され、途中のメッセージが再配信されると後続も連鎖して再配信されます。また pull 型サブスクリプションでは exactly-once 配信(同一リージョン内での再配信抑止)も有効化できます。「順序も重複排除も Pub/Sub 任せ」にはせず、まず受信側の冪等化で吸収し、本当に必要な箇所だけに絞るのが設計の定石です。ローカル開発にはエミュレータもあります(第 10 章参照)。

Dataflow と処理エンジンの選び分け

Dataflow — Apache Beam のマネージドランナー

Dataflow は、オープンソースの Apache Beam SDK(Java / Python / Go)で書いたパイプラインを実行するフルマネージドのデータ処理サービスです。最大の特徴はバッチとストリーミングを同じプログラミングモデルで書けること。ワーカー VM の割り当て・並列分散・完了後の破棄は Dataflow が自動で行い、負荷に応じた水平オートスケーリングと動的な作業再配分、Dataflow Prime による垂直オートスケーリングも備えます。レコード処理は既定で exactly-once(コストを優先するなら at-least-once モードも選択可)。Pub/Sub の at-least-once 配信と組み合わせても、集計結果に重複を持ち込まない変換層を作れるのが、図 11-1 のパイプラインで Dataflow が真ん中に座る理由です。

コードを書かずに使う道もあります。Google 提供テンプレートには「Pub/Sub から BigQuery へ」のような定番 ETL が用意されており、パラメータを与えるだけでジョブを起動できます。ノートブック(JupyterLab)での対話的開発もサポートされています。

Managed Service for Apache Spark と Cloud Composer(Managed Service for Apache Airflow)

Google Cloud Managed Service for Apache Spark(旧称 Dataproc。試験や既存資料では旧称で登場することがあります)は、Apache Spark / Hadoop エコシステムをマネージドで動かすサービスです。クラスタは 90 秒以内で起動でき、課金は秒単位(最低 1 分)。「ジョブのたびにクラスタを作り、終わったら消す」エフェメラルクラスタ運用でアイドルコストをなくせます。クラスタ管理すら不要な Managed Service for Apache Spark serverless(旧称 Serverless for Apache Spark / Dataproc Serverless)というデプロイ方式もあります。オンプレの Spark / Hadoop 資産を書き換えずに移行したいときの受け皿です。

Cloud Composer(2026-08 時点、公式ドキュメントの表記は Managed Service for Apache Airflow への移行中で、両名称が併存しています)は Apache Airflow のマネージド版で、役割がまったく異なります。Composer は処理エンジンではなくオーケストレーターです。Python で書いた DAG(タスクの依存関係グラフ)に従って、「BigQuery のロード → Dataflow ジョブ → 完了通知」のような複数サービスをまたぐワークフローをスケジュール・監視します。ハイブリッド / マルチクラウドのパイプラインもつなげます。

変換が SQL だけで完結する? (ELT パターン) BigQuery で ELT SQL だけで変換まで行う はい いいえ 既存の Spark / Hadoop 資産を そのまま動かしたい? Managed Spark (旧称 Dataproc) はい いいえ 新しくバッチ / ストリーミング 処理を実装する? Dataflow Apache Beam・exactly-once はい どのエンジンを選んでも、ジョブ間の依存関係とスケジュールの管理は Cloud Composer(Managed Service for Apache Airflow)がオーケストレーションを担う
図 11-5 処理エンジンのデシジョンツリー。Google Cloud で新規に作るなら Dataflow が既定解で、Managed Spark は「既存資産の移行」というシグナルで選ぶ。Composer はエンジンと競合せず、その上に載る指揮者。
試験の視点: データ分析系の選択問題はキーワードのマッピングでほぼ決まります。「既存の Hadoop / Spark ジョブを移行」→ Managed Service for Apache Spark(問題文では旧称 Dataproc のことが多い)。「バッチとストリーミングを統一的に処理」「Apache Beam」→ Dataflow。「グローバルな非同期メッセージング」「スパイク吸収」「疎結合化」→ Pub/Sub。「ワークフローの依存関係管理」「Airflow」→ Cloud Composer(Managed Service for Apache Airflow)。「サーバーレス DWH」「SQL 分析」→ BigQuery。この 5 語の対応と図 11-1 の並びを覚えるだけで、第 18 章のケーススタディ(IoT テレメトリ分析など)の骨格が読めるようになります。

ハンズオン

第 1 章で作った学習用プロジェクトと Cloud Shell を使います(ローカルの gcloud + bq でも同じです)。BigQuery と Pub/Sub はどちらも使った分だけの課金で、以下のハンズオンは無料枠にほぼ収まる分量に抑えています。

ハンズオン 11-1|bq CLI で公開データセットとパーティション分割テーブルを操作する

一般公開データセットへのクエリと、パーティション + クラスタリングによるスキャン削減を体験します。所要 15 分。費用: 無料枠内(クエリは月 1 TiB まで無料。本ハンズオンの合計スキャン量は数 GB 未満、作成するテーブルも数 MB でストレージ無料枠 10 GiB 内)。

  1. まずドライランでスキャン量を確認してから、ニューヨークのシェアサイクル公開データセットに集計クエリを実行します。--dry_run では課金は発生しません
# 実行前にスキャン量を確認(課金なし)
bq query --dry_run --use_legacy_sql=false \
'SELECT start_station_name, COUNT(*) AS num_trips
FROM `bigquery-public-data.new_york.citibike_trips`
GROUP BY start_station_name
ORDER BY num_trips DESC
LIMIT 10'

# 問題なければ本実行
bq query --use_legacy_sql=false \
'SELECT start_station_name, COUNT(*) AS num_trips
FROM `bigquery-public-data.new_york.citibike_trips`
GROUP BY start_station_name
ORDER BY num_trips DESC
LIMIT 10'

ドライランは「running this query will process N bytes of data」の形で処理予定バイト数を返します。本実行では乗車回数の多い駅トップ 10 が表形式で表示されます。

  1. 自分のデータセットを東京リージョンに作り、DDL で日単位パーティション + クラスタリング付きテーブルを生成データから作ります(約 70 日分・10 万行のダミーアクセスログ)
bq mk --location=asia-northeast1 -d pca_analytics

bq query --use_legacy_sql=false \
'CREATE TABLE pca_analytics.access_logs
PARTITION BY DATE(event_time)
CLUSTER BY user_id AS
SELECT
  TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL n MINUTE) AS event_time,
  CONCAT("user-", CAST(MOD(n, 50) AS STRING)) AS user_id,
  MOD(n, 5) AS response_class
FROM UNNEST(GENERATE_ARRAY(0, 99999)) AS n'
  1. プルーニングの効果をドライランで比較します。日付フィルタ付きのクエリは処理バイト数が大きく減るはずです。仕上げに --maximum_bytes_billed で「上限を超えるクエリは実行させない」ガードも試します
# 全期間スキャン
bq query --dry_run --use_legacy_sql=false \
'SELECT COUNT(user_id) FROM pca_analytics.access_logs'

# 当日パーティションのみ(バイト数が激減する)
bq query --dry_run --use_legacy_sql=false \
'SELECT COUNT(user_id) FROM pca_analytics.access_logs
WHERE DATE(event_time) = CURRENT_DATE()'

# 課金上限ガード: 上限 100 KB を超えるためエラーになり実行されない
bq query --maximum_bytes_billed=100000 --use_legacy_sql=false \
'SELECT COUNT(user_id) FROM pca_analytics.access_logs'

2 つのドライランで処理予定バイト数を見比べてください。パーティションを切っただけで、同じ意味のクエリのスキャン量(= オンデマンド課金額)が桁で変わることが確認できます。

後片付け:

bq rm -r -f pca_analytics
bq ls   # 一覧から消えたことを確認
ハンズオン 11-2|Pub/Sub のトピック・サブスクリプションとデッドレターを体験する

トピックとサブスクリプションを作り、publish / pull と ack の挙動、デッドレタートピックの設定を確認します。所要 15 分。費用: 無料枠内(Pub/Sub のメッセージ配信は月 10 GiB まで無料。本ハンズオンは数 KB)。

  1. 本体トピック・デッドレター用トピックと、それぞれのサブスクリプションを作ります。デッドレタートピック側にも回収用サブスクリプションを作るのを忘れずに
gcloud pubsub topics create orders
gcloud pubsub topics create orders-dlq

gcloud pubsub subscriptions create orders-sub --topic=orders \
  --dead-letter-topic=orders-dlq --max-delivery-attempts=5
gcloud pubsub subscriptions create orders-dlq-sub --topic=orders-dlq
  1. Pub/Sub のサービスアカウントに、デッドレター転送に必要な 2 つのロールを付与します(作成時に表示される権限の警告はこれで解消します)
PROJECT_NUMBER=$(gcloud projects describe \
  $(gcloud config get-value project) --format="value(projectNumber)")

gcloud pubsub topics add-iam-policy-binding orders-dlq \
  --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
  --role="roles/pubsub.publisher"

gcloud pubsub subscriptions add-iam-policy-binding orders-sub \
  --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
  --role="roles/pubsub.subscriber"
  1. publish して pull します。--auto-ack ありでは受信と同時に ack されメッセージは消えます。次に --auto-ack なしで pull すると、ack 期限(既定 10 秒)が切れた後に同じメッセージが再配信されることを確認できます — これが at-least-once の実物です
gcloud pubsub topics publish orders --message='{"order_id": 1001, "item": "coffee"}'
gcloud pubsub topics publish orders --message='{"order_id": 1002, "item": "tea"}'

# 受信と同時に ack(メッセージは消える)
gcloud pubsub subscriptions pull orders-sub --auto-ack --limit=5

# ack せずに受信 → 10 秒ほど待って再度 pull すると同じメッセージが再配信される
gcloud pubsub topics publish orders --message='{"order_id": 1003, "item": "cocoa"}'
gcloud pubsub subscriptions pull orders-sub --limit=5
gcloud pubsub subscriptions pull orders-sub --limit=5

ack されないメッセージがこのまま 5 回配信を超えると orders-dlq へ転送され、orders-dlq-sub から回収できる — というのが図 11-4 の流れです。

後片付け:

gcloud pubsub subscriptions delete orders-sub
gcloud pubsub subscriptions delete orders-dlq-sub
gcloud pubsub topics delete orders
gcloud pubsub topics delete orders-dlq
ハンズオン 11-3|Pub/Sub から BigQuery へ直接ストリーミングする(BigQuery サブスクリプション)

Dataflow もサブスクライバーのコードも書かずに、Pub/Sub のメッセージを BigQuery テーブルへ流し込みます。図 11-1 の点線ルートの実体験です。所要 20 分。費用: ほぼゼロ(BigQuery サブスクリプションのスループット課金 $50/TiB には無料枠がありませんが、本ハンズオンは数 KB なので 1 円未満。2026-08 時点)。

  1. 受け皿のデータセットとテーブルを作り、Pub/Sub のサービスアカウントに BigQuery への書き込み権限を付与します。スキーマ設定を使わない場合、メッセージ本文は data という名前の列(STRING / BYTES / JSON 型)に書き込まれるため、その名前で列を定義するのがポイントです
bq mk --location=asia-northeast1 -d pca_stream
bq mk --table pca_stream.raw_events data:STRING

PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" \
  --format="value(projectNumber)")

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
  --role="roles/bigquery.dataEditor"
  1. トピックを作り、--bigquery-table を指定して BigQuery サブスクリプションを作ります
gcloud pubsub topics create sensor-events

gcloud pubsub subscriptions create sensor-to-bq \
  --topic=sensor-events \
  --bigquery-table="${PROJECT_ID}.pca_stream.raw_events"
  1. メッセージを publish し、数秒待ってからテーブルを確認します。サブスクライバーを 1 行も書いていないのに行が増えていきます
gcloud pubsub topics publish sensor-events --message='{"device": "d-01", "temp": 21.5}'
gcloud pubsub topics publish sensor-events --message='{"device": "d-02", "temp": 23.0}'

# 数秒待ってから
bq query --use_legacy_sql=false 'SELECT data FROM pca_stream.raw_events'

2 行のメッセージ本文がそのまま data 列に入っていれば成功です。JSON の中身を列に展開したい場合はトピックスキーマ / テーブルスキーマを使う方式(--use-topic-schema / --use-table-schema)、メッセージをまたぐ集計や本格的な変換が必要になったら Dataflow へ、という段階論で考えます。

後片付け:

gcloud pubsub subscriptions delete sensor-to-bq
gcloud pubsub topics delete sensor-events
bq rm -r -f pca_stream

gcloud projects remove-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
  --role="roles/bigquery.dataEditor"

つまずきポイント

LIMIT や SELECT * ではスキャン量は減らない(課金の罠)。 BigQuery のオンデマンド課金は「返した行数」ではなく「スキャンしたバイト数」で決まります。LIMIT 10 を付けても(クラスタリングが効く場合を除き)テーブル全体がスキャンされ、SELECT * は全列分が課金されます。必要な列だけ選び、中身を眺めたいだけなら無料のプレビュー(bq head やコンソールのプレビュータブ)を使ってください。
パーティションはフィルタを書いて初めて効く。 パーティション分割テーブルでも、パーティション列への WHERE 句がなければ全区画スキャンです。分析者が複数いるテーブルでは、パーティションフィルタなしのクエリを拒否する設定(partition filter の必須化)を有効にしておくと事故を防げます。クラスタリングは実行前のコスト見積りが確定しない点にも注意(厳密なコスト管理が要るならパーティショニングを軸に)。
サブスクリプションのないトピックに publish したメッセージは失われる。 Pub/Sub はサブスクリプション作成以降のメッセージだけを配信します。「先に publish してからサブスクリプションを作った」場合、そのメッセージは受け取れません。またサブスクリプションは既定でサブスクライバーの活動が 31 日間ないと自動削除されます。「久しぶりに動かしたらサブスクリプションが消えていた」は学習環境でよく起きるので、消えていたら作り直してください。
デッドレターの設定は「トピックを指定して終わり」ではない。 Pub/Sub のサービスアカウントへ 2 つのロール(デッドレタートピックへの publisher、元サブスクリプションへの subscriber)を付与しないと、転送は行われず通常の再試行が延々と続きます。さらにデッドレタートピック自体にサブスクリプションがなければ、転送されたメッセージはそのまま失われます。ハンズオン 11-2 の手順①②はどちらも省略不可です。

理解度チェック

Q1. 日付範囲で絞る分析クエリのコストを「実行前に正確に」見積もれるようにしたい。パーティショニングとクラスタリングのどちらを軸にすべき?

パーティショニングです。パーティションのプルーニングは実行前のドライランに反映されるため、スキャン量(= オンデマンド課金額)を事前に確定できます。クラスタリングのブロック削減は実行後にしか確定しません。高カーディナリティの複数列で絞り込みたい場合は、パーティションの中をクラスタリングする併用が定番です。

Q2. Pub/Sub のサブスクライバーが同じメッセージを 2 回受け取った。これは異常か?

異常ではありません。Pub/Sub の配信保証は既定で at-least-once であり、ack が ack 期限(既定 10 秒)内に返らなかった場合などに再配信が起きます。受信処理は冪等に設計するのが原則で、どうしても重複を排除したい pull サブスクリプションでは exactly-once 配信を有効化できます(ただしリージョン内での保証)。

Q3. BigQuery のオンデマンド料金と容量ベース(エディション)料金は、それぞれ何に対して課金され、どう選び分ける?

オンデマンドはクエリがスキャンしたバイト数(TiB 単価、毎月 1 TiB 無料)、容量ベースは確保したスロットの時間(エディション、オートスケーリングと 1 / 3 年コミット割引あり)に課金されます。散発的・小規模ならオンデマンド、定常的に大量のクエリが走り月額を予測可能にしたいなら容量ベースが基本の選び分けです。オンデマンドの暴走対策としてカスタムクォータと maximum_bytes_billed も押さえておきましょう。

Q4.(試験形式)世界中の IoT デバイスから毎秒数万件のテレメトリを受信し、重複のない集計値をニアリアルタイムで SQL 分析基盤に蓄積したい。適切な構成は?
A. デバイス → Cloud SQL に直接書き込み B. デバイス → Pub/Sub → Dataflow → BigQuery C. デバイス → Cloud Storage → 夜間バッチで BigQuery D. デバイス → Memorystore → BigQuery

B。グローバルなイベント収集とスパイク吸収は Pub/Sub、exactly-once 処理での変換・集計は Dataflow、SQL 分析は BigQuery という標準ストリーミング構成です。A は書き込みスケールと分析用途の両面で不適。C はバッチであり「ニアリアルタイム」を満たしません。D の Memorystore はキャッシュであり収集・分析パイプラインの部品ではありません。

Q5.(試験形式)オンプレの Hadoop クラスタで動く夜間 Spark バッチを、コードをほぼ変えずにクラウドへ移行し、実行時間外のコストをなくしたい。最適な選択は?
A. Apache Beam に書き換えて Dataflow B. Managed Service for Apache Spark(旧称 Dataproc)のエフェメラルクラスタ C. すべて BigQuery の SQL に書き換える D. GKE に Spark を自前構築

B。「既存 Spark 資産をそのまま」「ジョブ実行時だけクラスタを起こす」という要件は、90 秒で起動し秒単位課金のエフェメラルクラスタ運用がぴったりです。A と C は「コードをほぼ変えずに」に反する書き換えコストが発生します。D は自前運用が残り、マネージドサービスを選ぶ Google Cloud の設計原則から外れます。

まとめと次章へ

ストレージとデータを巡る第 III 部はここまでです。次の第 12 章からは第 IV 部「接続とセキュリティ」に入り、オンプレミスとクラウドをつなぐハイブリッド接続と、組織スケールの VPC 設計パターンを扱います。

参考リンク(公式ドキュメント):