---
title: "Cloud SpannerとBigQueryの連携方法｜外部データセット・連携クエリ・変更ストリームの使い分け"
url: "https://www.issoh.co.jp/tech/details/4096/"
published: 2024-11-08
updated: 2026-08-05
categories: ["データベース"]
publisher: "株式会社一創"
---

# Cloud SpannerとBigQueryの連携方法｜外部データセット・連携クエリ・変更ストリームの使い分け

Cloud Spannerに貯まったトランザクションデータをBigQueryで集計したい、という要件を満たす経路は現在3つあります。設定の手間もコストの出方も制限も別物です。同じ「連携」という言葉で語られるため、外部データセットで済む案件にDataflowのパイプラインを組んでしまう選定ミスが起こります。

この記事では、外部データセット・連携クエリ・変更ストリームによる複製の3方式を、公式ドキュメントの構文と制限に沿って比較します。Spanner自体の仕組みやCloud SQLとの使い分け、料金構造は[Cloud Spannerとは？分散リレーショナルDBの仕組み・TrueTimeと採用判断を実装者目線で解説](/tech/details/15544/)で扱っているため、ここでは分析基盤へつなぐ部分に絞ります。

## まとめ：Spanner×BigQuery連携の3方式と選び分け

| 方式               | データの所在      | 準備           | Data Boost | 書き込み   | 鮮度      |
| ---------------- | ----------- | ------------ | ---------- | ------ | ------- |
| 外部データセット         | Spannerのまま  | DDL 1本       | 常時使用（変更不可） | 不可     | クエリ時点   |
| 連携クエリ            | Spannerのまま  | 接続リソース＋SQL   | 接続プロパティで選択 | 不可     | クエリ時点   |
| 変更ストリーム＋Dataflow | BigQueryへ複製 | DDL＋パイプライン運用 | 不要         | 複製先で自由 | 準リアルタイム |

まず外部データセットを試し、その制限に当たったときだけ連携クエリへ降りるのが最短です。BIツールから毎日フルスキャンする、履歴を長期保持する、複製先で加工したいといった要件が出た時点で、変更ストリームによる複製へ切り替えます。以降で各方式の構文と、実際に踏みやすい制限を見ていきます。

## Spannerのデータを分析側へ渡す3つの経路

### クエリ時に直接アクセスする2方式と、あらかじめ複製する1方式

外部データセットと連携クエリは、BigQueryがクエリのたびにSpannerを読みに行く直接アクセス方式です。ETLを挟まずSpannerのデータへ直接クエリするため、データはSpanner側に置いたまま。BigQueryのストレージ料金は増えず、参照した瞬間の値が返ります。その代わり、読むたびにSpanner側の計算資源（外部データセット経由では常にData BoostのSPU）を消費する構造です。

一方の変更ストリームは、Spannerの変更履歴を継続的に取り出してBigQueryのテーブルへ書き込む複製方式で、分析側に独立したコピーを作ります。差が出るのは運用の負担。前者の管理対象はデータセットか接続リソースだけですが、後者はDataflowジョブという常時稼働の構成要素が増えます。障害時に止まるのはジョブであり、止まった分だけ分析側のデータが遅れる構図です。

### 外部データセットと連携クエリを分ける「接続リソースの要否」

外部データセットは、Spannerのデータベースをまるごと1つのBigQueryデータセットとして見せます。テーブル名を書けばそのまま参照でき、接続リソースの作成は任意です。対して連携クエリは、`EXTERNAL_QUERY`関数の引数にSpanner側のSQLを文字列で渡す方式で、接続リソースの作成が前提になります。

Spanner側のSQLを自分で書けることが、連携クエリの実質的な価値です。集計や絞り込みをSpanner側で済ませてからBigQueryへ返せるため、転送される行数を意図的に減らせます。逆に言えば、テーブルをそのまま読むだけの用途で連携クエリを選ぶ理由はありません。

## 外部データセットの作成手順とGA後も残る制限

### CREATE EXTERNAL SCHEMAとexternal\_sourceの書式

Spanner外部データセットは一般提供（GA）済みで、BigQueryのクエリエディタからDDL 1本で作成できます。`external_source`にSpannerのデータベースを完全修飾名で指定し、`location`にBigQuery側のロケーションを指定します。ロケーションは作成後に変更できません。

```
CREATE EXTERNAL SCHEMA spanner_orders
  OPTIONS (
    external_source = 'google-cloudspanner:/projects/my_project/instances/my_instance/databases/my_database',
    location = 'asia-northeast1');
```

データベースロールを使う場合は、公式例の `google-cloudspanner://admin@/projects/my_project/...` のようにロール名を前置します。ロールを付けない形の公式例は `google-cloudspanner:/projects/...` とスラッシュが1本で、書式定義の `google-cloudspanner://[DATABASE_ROLE@]/projects/...` と見た目が変わります。公式例をそのまま写して合わせるのが確実です。コマンドラインからは `bq mk` でも同じことができます。

```
bq --location=asia-northeast1 mk --dataset \
    --external_source google-cloudspanner:/projects/my_project/instances/my_instance/databases/my_database \
    spanner_orders
```

### 書き込み不可とINFORMATION\_SCHEMA非対応が効いてくる場面

GAではあるものの、制限は少なくありません。公式ドキュメントが挙げるもののうち、設計に影響が大きいのは次の点です。

- テーブルのデータ・メタデータの追加、削除、更新ができない（DML不可）
- 外部データセット内にテーブル、ビュー、マテリアライズドビューを新規作成できない
- 参照できるのは既定スキーマのテーブルのみで、名前付きスキーマは対象外
- Spanner側で定義した主キーと外部キーはBigQuery側から見えない
- BigQueryが対応していない型の列は、その列だけアクセスできない
- INFORMATION\_SCHEMAビューとメタデータキャッシュに非対応
- 行レベルセキュリティ、列レベルセキュリティ、データマスキングに非対応

設計に効いてくるのはメタデータ系の制限です。データカタログやBIツールが`INFORMATION_SCHEMA`を舐めてスキーマを取得する作りだと、外部データセットだけスキーマ情報が取れずに一覧へ出てきません。アクセス制御も同様で、列レベルの権限分離が要件に入っている環境では、外部データセットのままでは要件を満たせず複製方式に倒す判断になります。

なお、外部データセットを参照するマテリアライズドビュー自体は、別のデータセットに作れます。公式には`max_staleness`と`allow_non_incremental_definition = true`を指定した非増分の例が示されており、同じ集計を何度も投げる用途ではこれで参照回数を抑えられます。

## 連携クエリ（EXTERNAL\_QUERY）を選ぶ条件と優先度の制御

### EXTERNAL\_QUERYの構文と実行優先度の指定

連携クエリでは、第1引数に接続、第2引数にSpanner側で実行するSQLを渡します。返ってきた結果はBigQuery側のテーブルと結合できます。

```
SELECT c.customer_id, c.name, rq.first_order_date
FROM mydataset.customers AS c
LEFT OUTER JOIN EXTERNAL_QUERY(
  'my-project.asia-northeast1.spanner_conn',
  '''SELECT customer_id, MIN(order_date) AS first_order_date
  FROM orders
  GROUP BY customer_id''') AS rq
  ON rq.customer_id = c.customer_id;
```

第3引数にはJSONでオプションを渡せます。`query_execution_priority`はhigh、medium、lowの3値で、既定はmediumです。夜間バッチのようにレイテンシを問わない処理をlowにしておくと、Spannerのオンライン処理と競合したときに分析側が後回しになります。

```
SELECT *
FROM EXTERNAL_QUERY(
  'my-project.asia-northeast1.spanner_conn',
  '''SELECT customer_id, MIN(order_date) AS first_order_date
  FROM orders
  GROUP BY customer_id''',
  '{"query_execution_priority":"low"}');
```

### 接続プロパティとFGAC利用時のデータベースロール指定

接続は`bq mk --connection`で作成し、`--connection_type=CLOUD_SPANNER`とプロパティのJSONを渡します。プロパティは`database`、`use_parallelism`、`useDataBoost`、`database_role`で、公式ドキュメント上もスネークケースとキャメルケースが混在しており、この表記がそのままキー名です。見た目を揃えず、ドキュメントどおりに書いてください。

```
bq mk --connection \
    --connection_type=CLOUD_SPANNER \
    --properties='{"database":"projects/my_project/instances/my_instance/databases/my_database","use_parallelism":true,"useDataBoost":true}' \
    --location=asia-northeast1 \
    --display_name='spanner-analytics' \
    spanner_conn
```

Spannerのきめ細かいアクセス制御（FGAC）を有効にしている環境では、データベースロールを指定した接続でなければ連携クエリが実行できません。実行するプリンシパルには`roles/spanner.fineGrainedAccessUser`と`roles/spanner.databaseRoleUser`が必要で、通常構成の`roles/spanner.databaseReader`だけでは足りない点に注意します。BigQuery側では接続の利用に`roles/bigquery.connectionUser`が要ります。

SpannerインスタンスとBigQueryデータセットのリージョンが異なる連携クエリも実行できますが、追加のデータ転送料金が発生します。東京リージョンのSpannerに対してUSのデータセットから毎日集計を投げる構成は、動きはするもののコスト面で不利です。

## Data Boostが本番インスタンスの負荷を切り離す条件

### 常時有効の外部データセットと、明示指定が要る連携クエリ

Data Boostは、Spannerに割り当てたコンピュートとは独立した計算資源で読み取りを処理するサーバーレス機能です。公式の定義は「独立したコンピュートリソースを提供するフルマネージドのサーバーレスサービス」で、分析クエリがオンライン処理のレイテンシを押し上げる事態を避けられます。

外部データセット経由のクエリは既定でData Boostを使い、この挙動は変更できません。一方の連携クエリでは接続プロパティでの明示が必要で、公式の指示は「Data Boostを有効にするには`useDataBoost`をtrueに、`use_parallelism`をtrueに設定する」というものです。並列読み取りとセットでしか有効になりません。

### 分散ユニオンが先頭になるクエリだけが対象

並列読み取りには前提条件があります。接続で並列読み取りを有効にした場合、実行プランの先頭のオペレーターが distributed union であるか、実行プランに distributed union を一切含まないかのどちらかである必要があり、どちらでもないクエリは「Query is not root partitionable」で失敗します。Data Boost側の説明も「対象となるのは、実行プランの最初のオペレーターが分散ユニオンであるクエリ」です。全てのクエリが自動で恩恵を受けるわけではないため、実行プランの確認は省けません。

権限も別枠です。`spanner.databases.useDataBoost`が必要で、これは`roles/spanner.admin`と`roles/spanner.databaseAdmin`には既定で含まれますが、閲覧目的のプリンシパルには`roles/spanner.databaseReaderWithDataBoost`を付与してください。`roles/spanner.databaseReader`だけを渡したプリンシパルはこの権限を持たないため、Data Boostを有効にした連携クエリは権限エラーになります。

### SPU単位の従量課金とエディションの扱い

Data Boostの課金はServerless Processing Unit（SPU）で、秒単位の計測に最低1分の課金が乗ります。固定費はなく、使った分だけの支払いです。単価はリージョンごとに異なるため、見積もりは公式の料金ページで確認してください。

エディション面での制約はありません。Standard、Enterprise、Enterprise Plusの3エディションいずれでも、BigQuery federationとSpanner Data Boostは利用できます。列指向エンジンや全文検索のように上位エディション限定の機能とは扱いが違い、Standardのままでも分析ワークロードの分離は成立します。

## 変更ストリーム（Spanner版のCDC）でBigQueryへ継続同期する構成

### CREATE CHANGE STREAMの構文と保持期間・値キャプチャ型

変更ストリームは、挿入・更新・削除をほぼリアルタイムで流し続けるスキーマオブジェクトです。テーブルやインデックスと同じくDDLで作成し、データベース全体か特定のテーブル・列を対象に指定します。

```
CREATE CHANGE STREAM EverythingStream FOR ALL;

CREATE CHANGE STREAM OrdersStream
  FOR Orders, OrderItems
  OPTIONS ( retention_period = '36h', value_capture_type = 'NEW_ROW' );
```

保持期間の既定は7日で、1日から30日の範囲で設定します。パイプラインが停止したときに巻き戻せる範囲がこの保持期間。上の例の36時間は既定より短い設定なので、復旧に必要な日数を確認してから縮めてください。値キャプチャ型は既定のOLD\_AND\_NEW\_VALUESのほか、NEW\_VALUES、NEW\_ROW、NEW\_ROW\_AND\_OLD\_VALUESの4種類。PostgreSQL方言のデータベースでは`OPTIONS`ではなく`WITH`を使います。

### Dataflowテンプレート・Kafkaコネクタ・Datastreamの選び分け

取り出した変更をBigQueryへ届ける手段は複数あります。もっとも手数が少ないのはDataflowのBigQuery向けテンプレートで、パイプラインを書かずに済む構成。処理を挟みたい場合はApache BeamのSpannerIOコネクタで自前のジョブを組みます。基盤側の詳細は[Cloud Dataflowとは？Apache Beamの実行基盤とストリーミング処理を実装者目線で解説](/tech/details/15553/)で整理しています。

既存のイベント基盤へ流すならKafkaコネクタ、パイプラインを運用したくないならDatastreamという選択肢もあります。Datastreamの対応ソース一覧では、MySQLやOracleとは別枠で「Spannerからも変更イベントをレプリケーションできる」と記載されており、Preview表記は付いていません。CDCの方式そのものの比較は[CDC（Change Data Capture）とは？3方式の仕組み・実装設定と採用判断を実装者目線で解説](/tech/details/15871/)を参照してください。

API直読みは中間コンポーネントを挟まないぶんレイテンシを抑えられますが、パーティションの追跡を自前で管理する必要があります。運用人員が確保できないチームが選ぶ構成ではありません。

## 3方式の選び分けと、クエリ時読み取りを選ぶべきでない場面

### 参照頻度・スキャン量・鮮度による判断基準

判断は次の順で降りるのが実務的です。参照が日に数回で、Spannerの1テーブルをそのまま見るだけなら外部データセットで足ります。Spanner側で絞り込んでから返したい、あるいは実行優先度を下げたいなら連携クエリです。BIツールが定期的に大量スキャンする、履歴を長期保持する、分析側で加工したいのいずれかに当てはまるなら、変更ストリームによる複製に切り替えます。

鮮度は複製方式の弱点に見えますが、実際に問題になるのは「秒単位で最新であること」が要件のときだけ。日次レポートや翌日確定の指標なら複製方式でも足ります。ただしコストの向きは逆で、複製側には常時稼働のDataflowワーカー費とBigQueryのストレージ料金が固定的に乗ります。参照回数が少ないうちは従量のSPU課金のほうが安く済むため、損益分岐は参照頻度とスキャン量で見積もってください。

### クエリ時読み取りが破綻する条件

次のケースでは、外部データセットも連携クエリも選ぶべきではありません。第一に、BigQuery側からSpannerのデータを書き換えたい場合。どちらの方式もDMLを受け付けないため、更新系は[リバースETLとは？同期モードと差分検出の仕組み・API制約から実装判断を解説【2026年版】](/tech/details/16107/)で扱う逆方向のパイプラインとして別に設計します。

第二に、列レベルセキュリティやデータマスキングを分析側で効かせたい場合。外部データセットはこれらに非対応で、連携クエリもSpannerが返した結果をそのまま扱う以上、BigQuery側の列レベルの制御は効きません。権限分離が要件なら、複製先のテーブルに対して設定します。第三に、ダッシュボードから同じ集計が何十回も飛ぶ場合です。読むたびにSpannerへ問い合わせが走るため、Data Boostを使っていてもSPUの消費が積み上がります。この3つに当たったら、迷わず複製へ倒します。

## Cloud SpannerとBigQueryの連携についてのよくある質問

### 外部データセットと連携クエリはどちらを先に検討すべきですか？

外部データセットです。接続リソースを作らずDDL 1本で用意でき、Data Boostも既定で有効になります。名前付きスキーマを使っている、INFORMATION\_SCHEMAが必要、Spanner側で集計を済ませたい、といった制限に当たった段階で連携クエリへ移ります。

### 連携クエリはSpannerの本番性能に影響しますか？

Data Boostが有効なら、独立したコンピュートで処理されるため既存ワークロードへの影響を避けられます。外部データセットは既定で有効ですが、接続経由の連携クエリは`useDataBoost`と`use_parallelism`を明示的にtrueにしていなければプロビジョニング済みのインスタンスを使います。加えて実行プランの先頭が分散ユニオンでなければ並列読み取りの対象外です。

### SpannerのCDCはどう実現しますか？

変更ストリームを作成し、Dataflowテンプレート、Beamコネクタ、Kafkaコネクタ、Datastream、API直読みのいずれかで消費します。変更履歴の保持は既定7日、最長30日です。

### BigQueryからSpannerのデータを更新できますか？

できません。外部データセットではテーブルのデータもメタデータも追加・削除・更新が禁じられており、連携クエリも読み取り専用です。更新が必要なら、アプリケーションまたは専用のパイプラインからSpannerのAPIを呼びます。

### Cloud SQLとSpannerでBigQuery連携の方法は違いますか？

接続タイプが異なります。Cloud SQL向けの接続は`CLOUD_SQL`、Spanner向けは`CLOUD_SPANNER`で、Data Boostや並列読み取りはSpanner固有の仕組みです。両者の使い分けそのものは[Cloud SQLとは？GCPのマネージドRDBの仕組み・エディションと採用判断を実装者目線で解説](/tech/details/15551/)で整理しています。

## 関連記事

- [Cloud Spannerとは？分散リレーショナルDBの仕組み・TrueTimeと採用判断を実装者目線で解説](/tech/details/15544/)
- [CDC（Change Data Capture）とは？3方式の仕組み・実装設定と採用判断を実装者目線で解説](/tech/details/15871/)
- [Cloud Dataflowとは？Apache Beamの実行基盤とストリーミング処理を実装者目線で解説](/tech/details/15553/)
- [Cloud SQLとは？GCPのマネージドRDBの仕組み・エディションと採用判断を実装者目線で解説](/tech/details/15551/)
- [リバースETLとは？同期モードと差分検出の仕組み・API制約から実装判断を解説【2026年版】](/tech/details/16107/)

---

出典: [Cloud SpannerとBigQueryの連携方法｜外部データセット・連携クエリ・変更ストリームの使い分け](<https://www.issoh.co.jp/tech/details/4096/>)（株式会社一創）
