Neo4j グラフデータベース
はじめに
ビジネスに多段の関連クエリが出てくると、リレーショナルデータベースの Join は途端に重たくなります。このノートでは、グラフデータベースである Neo4j について整理します。それが何であるか、料金体系はどうなっているか、データはどう組織されているか、そしてどんなシナリオで導入する価値があるか、です。
Neo4j は高性能なグラフデータベースで、グラフデータモデル(Graph Model) を採用してデータを保存・処理します。従来のリレーショナルデータベースと比べ、Neo4j は複雑なリレーションを持つデータの処理を得意とし、特に リレーション密度の高いデータシナリオ に適しています。
多くの業務システムでは、データ間に大量の関連関係が存在します。例えば:
- ソーシャルネットワークにおける友人関係
- レコメンドシステムにおけるユーザーと商品の関係
- ナレッジグラフにおけるエンティティ間の関係
- ネットワークセキュリティにおける攻撃経路の分析
これらのシナリオで従来のリレーショナルデータベースを使ってクエリすると、大量の Join 操作 が必要になり、クエリの複雑さも性能も急速に悪化します。一方グラフデータベースはリレーションを直接たどって走査できるため、複雑なリレーションを扱う際の効率がより高くなります。
なぜ Join がボトルネックになるのでしょうか。リレーショナルデータベースにおいて「リレーション」は第一級市民ではなく、外部キーと中間テーブルによって表現されます。Join を 1 段行うたびに、データベースはインデックス内で検索を行い、2 つのテーブルの行をマッチングしなければなりません。関連の段数が深くなり、データ量が増えるほど、このマッチングコストは急激に増加します。典型的な例が「友人の友人の友人」といったクエリです。MySQL では同じリレーションテーブルを 3 回自己結合する必要がありますが、グラフデータベースではポインタに沿って 2 歩余分に進むだけです。
料金モデル
公式サイト:Neo4j Graph Database & Analytics – The Leader in Graph Databases
Neo4j はオープンソースと商用ライセンスの 2 本立てモデルを採用しており、選定の前にまず 2 つのエディションの境界を把握しておくべきです。
Community Edition(コミュニティ版)
- オープンソースで無料
- 個人プロジェクトや中小規模のアプリケーションに適する
- 単一インスタンスのデプロイのみで、クラスタやオンラインホットスタンバイの機能は提供されない
Enterprise Edition(エンタープライズ版)
- 商用ライセンス
- クラスタ、高可用性、セキュリティ認証などの高度な機能を提供
- 可用性と権限管理に厳格な要件のある本番環境向け
簡単に言えば、機能検証、社内ツール、データ量がコントロール可能なシナリオならコミュニティ版で十分です。高可用性や細粒度の権限管理が要求されるようになった時点でエンタープライズ版は避けて通れず、このライセンスコストは事前に計画へ織り込んでおく必要があります。
グラフデータベースのデータ構造
グラフデータベースのデータ構造は次のとおりです
Node (ノード)
Relationship (リレーションシップ)
Property (プロパティ)
3 者の分担は明快です。ノードはエンティティ(人、商品、デバイス)を表し、リレーションシップはエンティティ間の接続を表し、必ず方向とタイプを持ちます。プロパティはノードまたはリレーションシップに付与されるキーバリューペアです。リレーショナルデータベースと対比して理解すると、ノードはテーブルの 1 行に、リレーションシップは外部キーに近いものです。ただしリレーションシップ自体もプロパティを持てる点(例えば「友人関係」に成立日時を保存できる)は、外部キーにはできないことです。
例:
(A)-[FRIEND]->(B)
(B)-[FRIEND]->(C)
リレーションシップは ノード間に直接保存されるポインタ です。データベースは リレーションシップのポインタに沿って走査する だけでよく、テーブル結合を行う必要がありません。そのため関連関係のクエリではリレーショナルデータベースをはるかに上回ります。この設計には専門の呼び名があり、インデックスフリー隣接(index-free adjacency) といいます。あるノードの隣接ノードを見つけるのにグローバルインデックスを経由せず、ノード自身のポインタから直接出発するため、1 ステップの走査コストはそのノードが持つリレーションシップの数だけに依存し、データベース全体のデータ量には依存しません。
クエリには Cypher 言語を使います。書き方は上のグラフ表記とほぼ一致しています:
// A の友人の友人を検索する(2 段のリレーション走査)
MATCH (a:Person {name: 'A'})-[:FRIEND]->()-[:FRIEND]->(fof)
RETURN fof.name
パターンマッチをそのまま絵に描いたものがクエリ文になる。これもグラフデータベースのモデリングが直感的である理由の一つです。
主要機能
グラフデータの保存とクエリ:Neo4j はグラフデータモデルを使ってデータを保存し、複雑なリレーションデータを容易に処理できます。
効率的なクエリ性能:グラフデータモデルの採用により、Neo4j は深いクエリや複雑なリレーションクエリを容易に処理でき、より高いクエリ性能を持ちます。クエリの所要時間は主に走査で通過するサブグラフの大きさに依存し、データベース全体の規模には依存しません。
拡張性:Neo4j は数百億のノードとリレーションシップまで容易にスケールでき、優れた拡張性を持ちます。
ACID トランザクションのサポート:Neo4j は ACID トランザクションをサポートし、データの整合性と信頼性を保証します。この点が、オフライン分析専用の多くのグラフ計算フレームワークとの違いです。Neo4j は分析ツールではなく、オンラインの書き込みを受け止められるデータベースなのです。
Neo4j はグラフデータモデルによってデータのリレーション表現をより直感的にし、複雑なリレーションクエリのシナリオで明確な性能優位を持ちます。従来の業務システムでは、リレーショナルデータベースが依然として中核的なデータストレージです。しかし リレーション密度の高いシナリオ(ソーシャルグラフ、レコメンドシステム、ナレッジグラフなど)では、グラフデータベースをリレーション分析エンジンとして、従来のデータベースと補完的に使うことができます。
ハマりどころと注意点
1)グラフデータベースをリレーショナルデータベースの代替にしないこと。集計統計や一括レポートのような列スキャン型のシナリオでは、グラフモデルに優位性はありません。合理的なアーキテクチャは通常、RDB がマスタデータを持ち、Neo4j がリレーションのサブセットを持つ形です。
2)モデリングの発想を切り替えること。グラフモデリングではまず「ノードは何か、リレーションシップは何と呼ぶか、方向はどちらか」を考え抜くのであって、先にテーブル構造を設計するのではありません。リレーションシップの方向やタイプを間違えて定義すると、後のクエリが非常に書きづらくなります。
3)走査の深さを制御すること。Cypher は可変長パスマッチングをサポートしているため、クエリで深さを限定しなかったりノードラベルを付けなかったりすると、簡単に全グラフスキャンへと発展し、インスタンス全体を巻き込んでしまいます。
導入の前に、実際のリレーションクエリで検証してください。ビジネス上のクエリの大半が 1、2 段の Join で済むなら、リレーショナルデータベースにインデックスをきちんと張れば十分なことが多く、もう一つストレージを運用する必要はありません。
まとめ
グラフデータベースが解決する核心的な問題はただ一つ、「リレーション」を第一級市民にし、Join をポインタ走査に置き換えることです。Neo4j のコミュニティ版はアイデアの検証に十分であり、本番の高可用性にはエンタープライズ版のライセンスを検討する必要があります。それはリレーショナルデータベースの代替品ではなく、リレーション密度の高いシナリオにおける補完エンジンです。クエリパターンが本当に深い関連走査であることを確認してから、導入を決めましょう。
COMMENTS