グラフデータベース — 友達の網を、引っ張ってたどる
SNSの「知り合いかも」は、友達の友達を探して出しています。これをいつもの表(RDBMS)でやろうとすると、「友達関係」の表を1段たどるたびに表を引き直すことになります。2人先、3人先と深くなるほど、SQLも処理も重くなる。
グラフデータベースは発想が逆です。人を点(ノード)、関係を線(エッジ)として、クモの巣の形のまましまいます。1人をつまんで引っ張れば、つながっている人がビヨーンとついてくる。その「つながりの手触り」がそのままデータの持ち方です。下の図1で、人をドラッグして網を引っ張ったり、クリックして起点にして友達の輪をたどったりしてみてください。
表でたどると、1段ごとに表を引き直す
RDBMSで友達関係を持つなら、friendships(user_id, friend_id) のような表に「誰と誰が友達か」を1行ずつ書きます。あおいさんの友達なら、この表から user_id = 'あおい' の行を探せば済みます。
問題は2段目からです。「友達の友達」は、見つかった友達1人1人について同じ表をもう一度引く必要があり、SQLでは表を自分自身と JOIN します。3人先なら JOIN が2つ、4人先なら3つ。しかも1回1回が全員分の友達関係が入った巨大な表を探す作業なので、会員が増えるほど1段あたりも重くなっていきます。
グラフDBは、隣への道を持っている
グラフDBでは、1人1人のノードが「自分の友達はこの人たち」という線を直接持っています。友達の友達を探すときも、巨大な表を探し直すのではなく、いまいる人から出ている線を順にたどるだけ。かかる手間はたどった線の本数で決まり、網全体が100人でも1億人でも、あおいさんのまわりの手間は変わりません。
問い合わせ言語も、この形に合わせてあります。Cypherの (a)-[:FRIEND*2]-(p) は、矢印の絵そのままに「友達の線を2本たどった先の人」。3人先にしたければ *3 にするだけです。「おすすめの友達」「不正送金の資金の流れ」「部品の依存関係」など、つながりを何段もたどる質問が主役のとき、グラフDBは強みを発揮します。
逆に、「全会員の平均年齢」「先月の売上合計」のような表全体をまとめて集計する質問は、RDBMSのほうが得意です。グラフDBは、たどる質問のための専用の道具だと考えるのがよいでしょう。
- ノード / エッジ
- グラフの点と線。人や商品がノード、「友達」「購入した」などの関係がエッジ。
- グラフデータベース
- ノードとエッジをそのまま保存し、関係をたどる問い合わせを得意とするDB。Neo4jなど。
- ホップ
- エッジを1本たどること。「友達の友達」は2ホップ先。
- 自己JOIN
- 同じ表を自分自身とつなぐJOIN。表で関係を何段もたどると、段数分だけ必要になる。
- Cypher
- グラフDB向けの問い合わせ言語。
(a)-[:FRIEND]->(b)のように、関係を矢印の絵で書く。
まとめ
グラフデータベースは、関係をクモの巣の形のまましまうデータベースです。表は「友達関係」を行として持つので、1段たどるたびに表を引き直し、JOIN が増えていきます。グラフDBは各ノードが隣への道を直接持っているので、手間はたどった線の本数だけ。つながりを何段もたどる質問が多いならグラフDB、表全体を集計するならRDBMS――データの「形」ではなく、よくする質問の形で選ぶのがコツです。