たなかこういちの開発ノート

システム開発に携わる筆者が、あれこれアウトプットするブログ

Graph DBの使い所

結局のところGraph DBはどういった場面によく適用できるのでしょうか?オブジェクト指向の言葉で、 RDBと対比しながら考察してみました。

 

 

RDBの広域構造と局所構造は次のように理解できます。
 
広域構造の特徴

 

テーブルはクラスの存在を、テーブルに格納されるレコードはインスタンスの存在を表現します。テーブルのリレーションは、クラス間の関連を表します。

 

局所構造の特徴

 

テーブルに定義されるカラムは、クラスの属性を表現します。カラムは平坦に並び、構造化データは表現しません。
 

f:id:tanakakoichi9230:20150305212838j:image

 
ここで強調すべきは、RDBのアーキテクチャーでは、表現されているのはクラス間の関連である、ということです。個々のインスタンスの関連の状況を個別に表現してはいない、という点です。
 
 
Graph DBは、Vertex(=頂点)とEdge(=辺)という要素から構成されます。多くのGraph DBでは、各Vertex、EdgeにPropertyを保持させることができます。
 

f:id:tanakakoichi9230:20150305212835j:image

 
Graph DBのこのアーキテクチャーは、RDBと比べてかなりプリミティブ(原始的)で、Vertex、Edgeに対してどのような解釈をも与えることができてしまいます。その中で、Vertexの存在がおおよそインスタンスの存在を表現しているとする見方が、ひとつ有効そうに思えます。Vertexがインスタンスを表しているとするなら、Edgeはインスタンス間の関係を表しているということになります。ここで注目すべきは、広域構造として、RDBでは、テーブル間のリレーションはクラスの関連を表現しており、インスタンス個々の関係を個別には表現し得ないのに対して、Graph DBではVertexの(Edgeによる)繋がりで個々のインスタンス間の関係を個別に表現可能である、という点です。あくまで説明のためのイメージとして、ですが、RDBのアーキテクチャーは、UMLクラス図で表現されるような内容を担うものであるのに対して、Graph DB(のこの解釈)はUMLオブジェクト図で表現されるような内容を担うことができる、というように説明できます。
 
一方、VertexやEdgeには原則として“型”の概念はありません。(RDBでは、個々のテーブル=クラスの存在が即ち“型”を表現しています。)幾つか擬似的に“型”を与える手法は存在するものの、いずれにせよGraph DBでは、RDBにおけるテーブルのように同一種類のVertexを集合として格納する“容れ物”を構造として持ち合わせていません。
 
Graph DBの、(RDBと異なり)クラス間の関連を表すというよりも個々のインスタンス間の関係を個別に表現し得るという特徴が活きる場面として以下のようなものを想定できます。
 
『多段階の階層構造を成していて、階層のネストのレベルが動的に変わるようなデータ構造を表現する』

 

階層のネストレベルが動的である場合、クラスレベルでの静的な定義では「無限段階のネストが可能である」との記述をするしかありません。このことが、RDBに落とした場合に「何回JOINする必要があるか、静的には記述できない」あるいは「多段階JOINを(DBMS提供機能とは別に)アプリケーションで実装しなければならない」という問題として現出します。Graph DBでは個々のインスタンス(Vertex)について、何段階のネストがあるのか具体的に関連(Edge)が“線引き”されていて、必要な処理はその線引きをDBMS提供機能を用いて”Traverse"するだけです。
 
 
前節では、「Vertexは(全て)クラスのインスタンスで、Edgeはインスタンス間の関係」と見立てましたが、ある種類のVertexをインスタンスの存在と見なす一方、そのVertexとある特定の種類のEdgeで関係しているVertexを、クラスの属性と見立てる設計も可能です。この見方の場合、それらのVertexおよびEdgeがデータの局所構造を表していることとなります。このとき属性たるEdge-Vertexを階層的に繋げることで、局所構造として構造化データも表現可能となります。
 
 
あるVertex、Edgeが広域構造(つまり、あるインスタンスと他のインスタンスの関係)を担っているのか局所構造(つまり、あるインスタンスの内部構造)を担っているのかについて、それを区別する仕組みがGraph DBネィティブに備わっている訳ではありません。(一部を除いて)Graph DBネィティブには“型”サポートは無いので、構築されたデータ構造を如何に“見立てる”のかは専らアプリケーション側でコントロールする問題となります。このことは、Graph DBを捉えどころの無いものに感じさせるかもしれません。
 
Graph DBは不定型なデータ構造を直接表現出来る能力を持つ一方、特定のドメインモデルを如何に実現するかについては常に一工夫が必要となる、と言えるでしょう。
 
その一工夫を乗り越えさえすれば、RDBが苦手とする、つまりRDBの「クラスとその関連」、「平坦なデータ構造」というアーキテクチャーでは表現し難い、不定段階階層データ、構造化データ、あるいは複数種類混在データを容易に扱うことができるようになるでしょう。
 
 

Graph DBが向かない場面はあるでしょうか?あくまで私見ですが、一般にOLTP的な使い方には向かないのではないか、という感触を持っています。多くのGraph DB製品はアトミックトランザクションもサポートするし、排他制御も実現しています。しかし、Graph DB各製品の排他制御の方式の特性によく習熟して使いこなさないと、簡単にデッドロックするか、パフォーマンスが出ないか、結局うまく排他制御できないか、いずれかに陥ります。これは「RDBにおけるテーブルのような“容れ物”が存在しない」ことに主に起因してい(ると私は理解してい)ます。「OLTPに全く適用できない」ということでは無いのですが、現時点では(必要な労力が少ない、という点で)RDBに一日の長があるだろう、と判断します。(※ちなみに、RDBにスケーラビリティやパフォーマンス面の不都合があったならKVSを検討する場面でしょう。)

 
 
<結論>
Graph DBは下記のような場面で効果的に適用できるのではないでしょうか。
 
(1) OLTPは従来通りにRDBに担わせ、そのRDBに蓄積されたデータに対して、個々のインスタンスの関係を表現するインデックスを張るというような位置付けでGraph DBを併設し、OLAP分野に役立たせる。
 
GraphのVertexのPropertyに、そのVertexが担うRDBのテーブルとレコードを識別するキーを保持させます。各インスタンスのデータ内容はRDBに保管しておく一方、個々のインスタンスの関係構造をGraph DBに外付けで構築します。

(2) 組織情報など、階層レベルが動的であるようなデータ構造を表現するのに用いる。なお、このとき当該情報はマスターデータであり、随時更新が発生するような情報で無いこと。
 
参考文献
 
- 「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜:
 
 
<追記>
本文で、Graph DBには“型”サポートが無いと説明しましたが、2013年以降リリースのNeo4j 2.x系では、「Label」というある種の“型”サポートが導入されています。あくまでイメージとして比喩として説明するものですが、Labelはある特別なVertexで、JavaScript等におけるプロトタイプベースのオブジェクト指向に類似した方式で、あるVertexがいずれの“型”であるかの表現をしている、と理解できます。
 
 
◆以上