
新機能 BigQuery Graph を触ってみた
データ事業本部のはんざわです。
4 月 9 日のアップデートで、BigQuery Graph が新機能として発表されました。
これまで BigQuery は、主に DWH としての分析基盤というイメージが強かったと思いますが、今後はグラフデータを扱うケースにも活用の幅が広がりそうです。
また、先日までラスベガスで開催された Google Cloud Next '26 でも本機能は大きく取り上げられており、注目度の高い機能であることが伺えます。
自分自身、これまでグラフデータベース(GDB)を扱った経験はありませんが、試しに触ってみたいと思います。
グラフデータベース(GDB)とは?
グラフデータベース(GDB)は、NoSQL データベースの一種で、ノード と エッジ からなるグラフ構造を用いて、エンティティとその関係性を表現するデータベースです。
-
ノード
- 一言で表現すると 点
- 人や商品、場所などの実体を表すエンティティ
-
エッジ
- 一言で表現すると 線
- ノード間の関係を表す要素
- 例として、「顧客」のノードと「商品」のノードの関係を「購入した」という関係を表現できます。
リレーショナルデータベース(RDB)とグラフデータベース(GDB)を各観点で比較すると以下のようになります。
| 機能 | リレーショナルデータベース(RDB) | グラフデータベース(GDB) |
|---|---|---|
| データ構造 | 行と列からなる表形式 事前定義されたプロパティを持つ厳密なスキーマで扱う |
ノードとエッジからなるグラフ構造 関係性を柔軟に表現しやすい |
| クエリ効率 | JOIN 操作でテーブルを結合するため、関係が増えるほどクエリが遅くなったり、複雑になったりしやすい | エッジを直接辿れるため、関係性に焦点を当てたクエリでは直感的になりやすい |
| クエリ言語 | SQL(Structured Query Language) | GQL(Graph Query Language) |
| ユースケース | 財務システムや在庫管理など、構造化され予測可能な業務データを扱う用途に向いている | ソーシャルネットワーク、不正検知、経路最適化など、関係性の分析が中心となる用途に向いている |
GQL とは?
BigQuery Graph では、GQL(グラフクエリ言語)を使ってグラフデータをクエリします。
GQL の構文は従来の SQL と書き方が大きく異なるため、慣れるまで少し時間がかかるかもしれません。
具体的な構文は、以下のドキュメントが参考になりそうです。
例として、「顧客」の「A さん」が購入した全ての「商品名」を取得したいとします。
この場合、以下のようなクエリになります。
GRAPH ShopGraph
MATCH (c:顧客 {顧客名: 'A さん'})-[:購入した]->(p:商品)
RETURN p.商品名
このクエリでは、GRAPH で対象となるグラフを指定し、MATCH でノードとエッジの関係をたどります。{} の中ではノードのプロパティ条件を指定でき、ここでは 顧客名 が A さん の顧客を表しています。最後に RETURN で、取得したい商品名を返します。
逆に、「商品」の「B」を購入した全ての顧客名を取得したいとします。
この場合、クエリは以下のようになります。
GRAPH ShopGraph
MATCH (p:商品 {商品名: 'B'})<-[:購入した]-(c:顧客)
RETURN c.顧客名
最初のクエリでは「顧客」から「商品」へ辿っていましたが、このクエリでは逆に「商品」から「顧客」を辿っています。そのため、購入した のエッジの向きも <-[:購入した]- という形で逆向きに記述されています。
これらのパターンは、MATCH 文の中でグラフパターンとして記述します。詳しくは、以下のドキュメントも併せて確認してみてください。
最後に、少し複雑な例を試してみます。
以下のクエリでは、「顧客」の「A さん」が購入した商品を他にも購入した顧客の「顧客名」とその「商品名」を取得できます。
GRAPH ShopGraph
MATCH (a:顧客 {顧客名: 'A さん'})-[:購入した]->(p:商品)<-[:購入した]-(c:顧客)
WHERE c != a
RETURN c.顧客名, p.商品名
このクエリは、NEXT 文を使って段階的に記述することもできます。NEXT では前段の結果が次段に引き継がれます。
FILTER はその結果行に対して条件を適用する構文で、見た目は WHERE に似ていますが、前段から渡された列も参照できる点が特徴です。ここでは c != a とすることで A さん本人を除外しています。
GRAPH ShopGraph
MATCH (a:顧客 {顧客名: 'A さん'})-[:購入した]->(p:商品)
RETURN a, p
NEXT
MATCH (p)<-[:購入した]-(c:顧客)
FILTER c != a
RETURN c.顧客名, p.商品名
ここまで紹介したのは、GQL の基本的な書き方の一部です。詳しい構文については、上記の公式ドキュメントも併せて確認してみてください。
実際に試してみる
早速ですが、前段で紹介した例を BigQuery Graph 上で実際に再現してみたいと思います。
1. サンプルデータの準備
まずは、サンプルデータを準備します。
上記の関係を表現するため、以下の 3 テーブルを作成します。
- 顧客テーブル
- 商品テーブル
- 顧客と商品の購入関係を表すブリッジテーブル
1 と 2 はノード、3 はエッジとして扱いますが、実体は通常のテーブルとして作成します。
CREATE OR REPLACE TABLE `sample_graph.customers` (
customer_id INT64 PRIMARY KEY NOT ENFORCED,
customer_name STRING
);
INSERT INTO `sample_graph.customers` (customer_id, customer_name)
VALUES
(1, 'A さん'),
(2, 'B さん'),
(3, 'C さん'),
(4, 'D さん'),
(5, 'E さん');
CREATE OR REPLACE TABLE `sample_graph.products` (
product_id INT64 PRIMARY KEY NOT ENFORCED,
product_name STRING,
category STRING,
price INT64
);
INSERT INTO `sample_graph.products` (product_id, product_name, category, price)
VALUES
(101, 'りんご', '食品', 120),
(102, 'ミネラルウォーター', '飲料', 180),
(103, 'ノート', '文房具', 150),
(104, 'ボールペン', '文房具', 200),
(105, 'トイレットペーパー', '日用品', 300),
(106, 'コーヒー豆', '食品', 450),
(107, 'ワイヤレスイヤホン', '家電', 1200),
(108, 'モバイルバッテリー', '家電', 2400);
CREATE OR REPLACE TABLE `sample_graph.customer_product_bridge` (
purchase_id INT64 PRIMARY KEY NOT ENFORCED,
customer_id INT64 REFERENCES `sample_graph.customers` (customer_id) NOT ENFORCED,
product_id INT64 REFERENCES `sample_graph.products` (product_id) NOT ENFORCED,
purchased_at DATE
);
INSERT INTO `sample_graph.customer_product_bridge`
(purchase_id, customer_id, product_id, purchased_at)
VALUES
(1, 1, 101, DATE '2026-04-01'), -- A さん -> りんご
(2, 1, 102, DATE '2026-04-02'), -- A さん -> ミネラルウォーター
(3, 1, 103, DATE '2026-04-03'), -- A さん -> ノート
(4, 2, 102, DATE '2026-04-02'), -- B さん -> ミネラルウォーター
(5, 2, 104, DATE '2026-04-03'), -- B さん -> ボールペン
(6, 2, 105, DATE '2026-04-04'), -- B さん -> トイレットペーパー
(7, 3, 101, DATE '2026-04-01'), -- C さん -> りんご
(8, 3, 102, DATE '2026-04-02'), -- C さん -> ミネラルウォーター
(9, 3, 106, DATE '2026-04-05'), -- C さん -> コーヒー豆
(10, 4, 103, DATE '2026-04-03'), -- D さん -> ノート
(11, 4, 107, DATE '2026-04-06'), -- D さん -> ワイヤレスイヤホン
(12, 5, 102, DATE '2026-04-02'), -- E さん -> ミネラルウォーター
(13, 5, 103, DATE '2026-04-03'), -- E さん -> ノート
(14, 5, 108, DATE '2026-04-07'); -- E さん -> モバイルバッテリー
2. プロパティグラフの作成
プロパティグラフは、CREATE PROPERTY GRAPH の構文で作成できます。
NODE TABLES にはノードに相当するテーブルを指定し、EDGE TABLES にはエッジに相当するテーブルを指定します。また、EDGE TABLES では SOURCE KEY と DESTINATION KEY を指定することで、どのノード同士を結ぶかを表現できます。
CREATE OR REPLACE PROPERTY GRAPH sample_graph.ShopGraph
NODE TABLES (
`sample_graph.customers` AS Customer
LABEL customer,
`sample_graph.products` AS Product
LABEL product
)
EDGE TABLES (
`sample_graph.customer_product_bridge` AS Purchase
SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
DESTINATION KEY (product_id) REFERENCES Product (product_id)
);
最終的に、データセット配下は以下のようになりました。

さらに、コンソールから各ノードの関係を視覚的に確認することもできます。

3. 試してみる
先ほどの例に沿って、実際に以下の 3 パターンを試してみます。
- A さんが購入した全ての商品名を取得
- ミネラルウォーターを購入した顧客名を取得
- A さんと同じ商品を購入した顧客名とその商品名を取得
3.1. A さんが購入した全ての商品名を取得
GRAPH sample_graph.ShopGraph
MATCH (c:customer {customer_name: 'A さん'})-[:Purchase]->(p:product)
RETURN p.product_name
A さんが購入した商品として、りんご・ミネラルウォーター・ノートが返っていることが分かります。

3.2. ミネラルウォーターを購入した顧客名を取得
GRAPH sample_graph.ShopGraph
MATCH (p:product {product_name: 'ミネラルウォーター'})<-[:Purchase]-(c:customer)
RETURN c.customer_name
ミネラルウォーターを購入した顧客名として、A さん・B さん・C さん・E さんが返っていることが分かります。

3.3. A さんと同じ商品を購入した顧客名とその商品名を取得
GRAPH sample_graph.ShopGraph
MATCH (a:customer {customer_name: 'A さん'})-[:Purchase]->(p:product)
RETURN a, p
NEXT
MATCH (p)<-[:Purchase]-(c:customer)
FILTER c != a
RETURN c.customer_name, p.product_name

また、GQL の実行結果を SQL で利用することも可能です。
SELECT
customer_name,
product_name
FROM
GRAPH_TABLE(
sample_graph.ShopGraph
MATCH (a:customer {customer_name: 'A さん'})-[:Purchase]->(p:product)
RETURN a, p
NEXT
MATCH (p)<-[:Purchase]-(c:customer)
FILTER c != a
RETURN c.customer_name, p.product_name
)
ORDER BY customer_name;

おまけ
グラフのスキーマ設計とクエリのベストプラクティスがドキュメントで紹介されています。併せて確認してみてください。
また、公式のチュートリアルも複数用意されているので、興味があればぜひ試してみてください。
さいごに
今回のブログでは、新機能の BigQuery Graph を実際に試してみました。グラフデータベースの基礎を理解する良い機会にもなりました。
さらに、4 月 22 日には、BigQuery Graph の新機能として、measures の定義や Conversational Analytics から自然言語でグラフを問い合わせる機能などの機能も追加されていました。今後の進化にも期待が高まります。
今後は、これらの機能についても実際に試してみたいと思います。






