BigQuery Graphでプロパティグラフを定義してGQLによるグラフ分析を試してみる

BigQuery Graphでプロパティグラフを定義してGQLによるグラフ分析を試してみる

2026.06.01

タイトル候補

  1. BigQuery Graphでプロパティグラフを定義してGQLによるグラフ分析を試してみる
    • おすすめ理由:機能名・標準言語のGQL・操作内容を盛り込み、著者の「〜してみる」語尾とも整合する王道タイトル。
  2. BigQueryのテーブルを使ってGQLで2ホップの送金関係を直感的にクエリしてみた
    • おすすめ理由:SQLでの複雑なJOINがGQLで簡潔になるという記事の効能を具体例で訴求し読者の関心を引きやすい。
  3. データアナリスト向けにBigQuery Graphで不正検知やネットワーク分析を始めるための第一歩を試してみた
    • おすすめ理由:分析者という読者対象を絞りユースケースを前面に出すことで、対象読者に刺さりやすい構成にした。

おすすめは 1番。機能名・GQL・「試してみる」の3要素が揃い、検索性と著者の命名傾向への適合度が最も高いため。

はじめに

データアナリティクス事業本部のkobayashiです。

2026年4月9日にBigQuery Graphがプレビューとして公開されました。BigQueryのテーブルデータをグラフ(ノードとエッジ)としてモデリングし、Graph Query Language(GQL) で分析できる機能です。

これまでBigQueryでグラフ的な分析を行うにはSQLで複雑なJOINや再帰CTEを書く必要がありましたが、BigQuery GraphではISO GQL / SQL/PGQ をベースにしたグラフクエリで直感的に記述できます。

BigQuery Graphとは

BigQuery Graphは、既存のBigQueryテーブルをノード(頂点)とエッジ(辺)として定義し、プロパティグラフを構築する機能です。

主な特徴

項目 内容
ステータス Preview
グラフ標準 ISO GQL / ISO SQL/PGQ 互換
対応エディション Enterprise または Enterprise Plus(リザベーション必須)
ストレージ 追加ストレージ不要(既存テーブルを参照)
コンピュート スロットベースの容量課金

従来のSQLとの比較

例えば「AさんがBさんにお金を送金し、Bさんがさらに別の人に送金した」というような2ホップの関係を調べる場合、従来のSQLでは複数のJOINが必要でした。

従来のSQL:

SELECT
  p1.name AS sender,
  t1.amount,
  p2.name AS receiver
FROM Person p1
JOIN PersonOwnAccount poa1 ON p1.id = poa1.id
JOIN AccountTransferAccount t1 ON poa1.account_id = t1.id
JOIN Account a2 ON t1.to_id = a2.id
JOIN PersonOwnAccount poa2 ON a2.id = poa2.account_id
JOIN Person p2 ON poa2.id = p2.id
WHERE p1.name = 'Dana';

GQL:

GRAPH FinGraph
MATCH
  (p1:Person {name: "Dana"})-[:Owns]->(a1:Account)
    -[t:Transfers]->(a2:Account)<-[:Owns]-(p2:Person)
RETURN p1.name AS sender, t.amount, p2.name AS receiver;

GQLではグラフの関係をパターンとして直接記述できるため、クエリが直感的で可読性が高くなります。

では早速試してみます。

BigQuery Graphを試してみる

公式ドキュメントのチュートリアルに沿って、金融取引のグラフを作成して分析してみます。

1. データセットの作成

CREATE SCHEMA IF NOT EXISTS graph_db;

2. ノードテーブルの作成

グラフのノード(頂点)となるテーブルを作成します。

Person テーブル(人物ノード):

CREATE OR REPLACE TABLE graph_db.Person (
  id        INT64,
  name      STRING,
  birthday  TIMESTAMP,
  country   STRING,
  city      STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

Account テーブル(口座ノード):

CREATE OR REPLACE TABLE graph_db.Account (
  id          INT64,
  create_time TIMESTAMP,
  is_blocked  BOOL,
  nick_name   STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

3. エッジテーブルの作成

グラフのエッジ(辺)となるテーブルを作成します。

PersonOwnAccount テーブル(人物→口座の所有関係):

CREATE OR REPLACE TABLE graph_db.PersonOwnAccount (
  id          INT64 NOT NULL,
  account_id  INT64 NOT NULL,
  create_time TIMESTAMP,
  PRIMARY KEY (id, account_id) NOT ENFORCED,
  FOREIGN KEY (id) REFERENCES graph_db.Person(id) NOT ENFORCED,
  FOREIGN KEY (account_id) REFERENCES graph_db.Account(id) NOT ENFORCED
);

AccountTransferAccount テーブル(口座間の送金関係):

CREATE OR REPLACE TABLE graph_db.AccountTransferAccount (
  id           INT64 NOT NULL,
  to_id        INT64 NOT NULL,
  amount       FLOAT64,
  create_time  TIMESTAMP NOT NULL,
  order_number STRING,
  PRIMARY KEY (id, to_id, create_time) NOT ENFORCED,
  FOREIGN KEY (id) REFERENCES graph_db.Account(id) NOT ENFORCED,
  FOREIGN KEY (to_id) REFERENCES graph_db.Account(id) NOT ENFORCED
);

4. サンプルデータの投入

-- 口座データ
INSERT INTO graph_db.Account (id, create_time, is_blocked, nick_name)
VALUES
  (7, "2020-01-10 06:22:20.222", false, "Vacation Fund"),
  (16, "2020-01-27 17:55:09.206", true, "Vacation Fund"),
  (20, "2020-02-18 05:44:20.655", false, "Rainy Day Fund");

-- 人物データ
INSERT INTO graph_db.Person (id, name, birthday, country, city)
VALUES
  (1, "Alex", "1991-12-21 00:00:00", "Australia", "Adelaide"),
  (2, "Dana", "1980-10-31 00:00:00", "Czech_Republic", "Moravia"),
  (3, "Lee", "1986-12-07 00:00:00", "India", "Kollam");

-- 送金データ
INSERT INTO graph_db.AccountTransferAccount (id, to_id, amount, create_time, order_number)
VALUES
  (7, 16, 300, "2020-08-29 15:28:58.647", "304330008004315"),
  (7, 16, 100, "2020-10-04 16:55:05.342", "304120005529714"),
  (16, 20, 300, "2020-09-25 02:36:14.926", "103650009791820"),
  (20, 7, 500, "2020-10-04 16:55:05.342", "304120005529714"),
  (20, 16, 200, "2020-10-17 03:59:40.247", "302290001255747");

-- 口座所有関係
INSERT INTO graph_db.PersonOwnAccount (id, account_id, create_time)
VALUES
  (1, 7, "2020-01-10 06:22:20.222"),
  (2, 20, "2020-01-27 17:55:09.206"),
  (3, 16, "2020-02-18 05:44:20.655");

5. プロパティグラフの作成

CREATE PROPERTY GRAPH 文でノードテーブルとエッジテーブルを指定してグラフを定義します。

CREATE OR REPLACE PROPERTY GRAPH graph_db.FinGraph
  NODE TABLES (
    graph_db.Account,
    graph_db.Person
  )
  EDGE TABLES (
    graph_db.PersonOwnAccount
      SOURCE KEY (id) REFERENCES Person (id)
      DESTINATION KEY (account_id) REFERENCES Account (id)
      LABEL Owns,
    graph_db.AccountTransferAccount
      SOURCE KEY (id) REFERENCES Account (id)
      DESTINATION KEY (to_id) REFERENCES Account (id)
      LABEL Transfers
  );

ポイントは以下です。

  • NODE TABLES でノードとなるテーブルを指定
  • EDGE TABLES でエッジとなるテーブルを指定し、SOURCE KEYDESTINATION KEY で接続先のノードを定義
  • LABEL でエッジにラベルを付与(GQLクエリでの参照に使用)
  • グラフ定義は既存テーブルへの参照であり、データの複製は行われない

6. GQLでグラフをクエリ

グラフが作成できたのでGQLでクエリしてみます。

Danaの口座から送金先の人物を取得:

GRAPH graph_db.FinGraph
MATCH
  (person:Person {name: "Dana"})-[own:Owns]->
  (account:Account)-[transfer:Transfers]->(account2:Account)
  <-[own2:Owns]-(person2:Person)
RETURN
  person.name AS owner,
  transfer.amount AS amount,
  person2.name AS transferred_to
ORDER BY person2.name;

MATCH 句でグラフのパターンを指定します。() がノード、-[]-> がエッジ(方向付き)を表します。:Person:Owns はラベルによるフィルタ、{name: "Dana"} はプロパティによるフィルタです。

GQLの主な構文

MATCH(パターンマッチング)

-- 基本的なパターンマッチ
GRAPH graph_db.FinGraph
MATCH (p:Person)-[:Owns]->(a:Account)
RETURN p.name, a.nick_name;

FILTER(条件フィルタリング)

GRAPH graph_db.FinGraph
MATCH (a1:Account)-[t:Transfers]->(a2:Account)
FILTER t.amount > 200
RETURN a1.id AS from_account, a2.id AS to_account, t.amount;

LET(変数束縛)

LET は式の結果に別名を付けて後続の RETURN で参照できるようにする構文です。

GRAPH graph_db.FinGraph
MATCH (a:Account)-[t:Transfers]->(a2:Account)
LET amount_jpy = t.amount * 150
RETURN a.id AS from_id, a2.id AS to_id, amount_jpy;

なお集約をしたい場合は LET ではなく RETURN 句で集約関数と GROUP BY を使います。

GRAPH graph_db.FinGraph
MATCH (a:Account)-[t:Transfers]->(:Account)
RETURN a.id AS account_id, SUM(t.amount) AS total
GROUP BY account_id;

NEXT(クエリの連結)

NEXT キーワードで複数のクエリステートメントを連結できます。

GRAPH graph_db.FinGraph
MATCH (p:Person)-[:Owns]->(a:Account)
RETURN p.name AS person_name, a.id AS account_id
NEXT
MATCH (a:Account)-[t:Transfers]->(a2:Account)
WHERE a.id = account_id
RETURN person_name, t.amount, a2.id AS to_account;

GRAPH_TABLE(SQLとの統合)

GRAPH_TABLE 演算子を使うことで、GQLクエリの結果を通常のSQLクエリの一部として利用できます。

SELECT *
FROM GRAPH_TABLE(
  graph_db.FinGraph
  MATCH (p:Person)-[:Owns]->(a:Account)-[t:Transfers]->(a2:Account)
  RETURN p.name, t.amount, a2.id AS to_account
)
WHERE amount > 200
ORDER BY amount DESC;

グラフの可視化

パスを TO_JSON でJSON形式に変換して返すことで、BigQueryコンソールやノートブック上でノードとエッジのグラフ構造を視覚的に確認できます。

GRAPH graph_db.FinGraph
MATCH
  p = ((person:Person)-[own:Owns]->(account:Account)
    -[transfer:Transfers]->(account2:Account)
    <-[own2:Owns]-(person2:Person))
RETURN TO_JSON(p) AS path;

BigQueryコンソール上での確認

BigQueryコンソール(BigQuery Studio)で上記GQLを実行すると、クエリ結果ペインに 「グラフ プレビュー」タブ が自動表示されます。ノード(Person/Account)が色分けされ、エッジ(Owns/Transfers)にもラベルが付与されてインタラクティブに描画されます。

BigQuery Graph 可視化(Account ノードを選択した状態)

各ノードをクリックすると、左側に ラベル / プロパティ / 近傍ノード が一覧表示されます。たとえば Account ノード(id=16, nick_name="Vacation Fund", is_blocked=true)を選ぶと、その口座が接続されている Person ノードや、送金(Transfers)でつながった他の Account ノードを辿れます。

BigQuery Graph 可視化(別の Account ノードを選択した状態)

BigQueryノートブックでの確認

BigQueryノートブックでは %%bigquery --graph マジックコマンドを使うと、同様のグラフ可視化が得られます。

%%bigquery --graph
GRAPH graph_db.FinGraph
MATCH
  p = ((person:Person)-[own:Owns]->(account:Account)
    -[transfer:Transfers]->(account2:Account)
    <-[own2:Owns]-(person2:Person))
RETURN TO_JSON(p) AS path;

GQLで利用可能なグラフ関数

GQLでは以下のグラフ固有の関数が利用できます。

関数 説明
PATH_LENGTH(path) パスの長さ(エッジ数)
EDGES(path) パスに含まれるエッジの配列
NODES(path) パスに含まれるノードの配列
ELEMENT_ID(element) ノードまたはエッジのID
SOURCE_NODE_ID(edge) エッジのソースノードID
DESTINATION_NODE_ID(edge) エッジのデスティネーションノードID

利用条件と注意事項

  • エディション要件: Enterprise または Enterprise Plus エディションのリザベーションが必要(オンデマンドでは利用不可)
  • ストレージ: グラフ定義は既存テーブルへの参照であり、追加のストレージ料金は発生しない
  • コンピュート: グラフクエリはスロットベースの容量課金
  • ステータス: 現在プレビュー段階のため、本番利用には注意が必要

ユースケース

BigQuery Graphは以下のような分析に活用できます。

  • 不正検知: 送金ネットワークの異常パターン検出
  • ソーシャルネットワーク分析: ユーザー間の関係性やインフルエンサーの特定
  • サプライチェーン分析: 部品・製品の依存関係の可視化
  • Customer 360: 顧客の行動・関係性の包括的な分析
  • ナレッジグラフ: エンティティ間の関係構築と検索

グラフの削除

不要になったグラフ定義は DROP PROPERTY GRAPH で削除できます。グラフ定義を削除しても元のテーブルには影響しません。

DROP PROPERTY GRAPH graph_db.FinGraph;

まとめ

BigQuery Graphを紹介しました。

  • 既存のBigQueryテーブルからプロパティグラフを定義し、GQLで分析可能
  • ISO標準のGQLで複雑なグラフ関係を直感的に記述
  • GRAPH_TABLE 演算子でSQLとGQLの統合が可能
  • BigQueryノートブックでグラフの可視化にも対応
  • Enterprise / Enterprise Plus エディションが必要(プレビュー)

従来SQLで書くと複雑になりがちだったグラフ分析がGQLで簡潔に書けるようになり、BigQueryの分析の幅が大きく広がります。

最後まで読んで頂いてありがとうございました。

この記事をシェアする

関連記事