似たようなアイテム(数百万)をたくさん使ってアプリケーションを作成し、それらをMySQLデータベースに保存したいと思います。多くの統計を実行し、特定の列の特定の値を検索したいからです。
しかし同時に、多くの接続された二分木のような構造(推移閉包)に関連するすべてのアイテム間の関係を格納します。リレーショナルデータベースはそのような構造が苦手なので、格納したいと思います。この種のデータに対して良好なパフォーマンスを持つNeo4jのすべての関係。
私の計画では、MySQLデータベースの関係とitem_id
とのすべての関係を除くすべてのデータをNeo4jデータベースに保存する予定です。ツリーを検索するときは、最初にツリー内のすべてのitem_id
:sをNeo4jで検索し、次に次のようなクエリで指定されたすべてのアイテムをMySQLデータベースで検索します。
SELECT * FROM items WHERE item_id = 45 OR item_id = 345435 OR item_id = 343 OR item_id = 78 OR item_id = 4522 OR item_id = 676 OR item_id = 443 OR item_id = 4255 OR item_id = 4345
これは良い考えですか、それとも私は非常に間違っていますか? 私はこれまでグラフデータベースを使用したことがありません。私の問題に対するより良いアプローチはありますか?この場合、MySQLクエリはどのように実行されますか?
これについてのいくつかの考え:
Neo4jドメインモデルをモデル化して、グラフに各ノードの属性を含めてみます。データを2つの異なるデータストアに分割することにより、実行したい操作を制限する場合があります。
私はそれがあなたがあなたのグラフで何をするかということに帰着すると思います。たとえば、属性(名前、年齢など)が特定の値である特定のノードに接続されているすべてのノードを検索する場合は、最初にMySQLデータベースで正しいノードIDを検索してから、に移動する必要があります。 Neo4j? Neo4jでこれらすべてを実行できる場合、これは遅く、非常に複雑に見えます。したがって、問題は、グラフをトラバースするときにノードの属性が必要になるかどうかです。
データは変更されますか、それとも静的ですか? 2つの別々のデータストアを持つことにより、問題が複雑になります。
MySQLデータベースを使用して統計を生成することは、Neo4jですべてを実行するよりも簡単かもしれませんが、定義された基準を満たすすべてのノードを見つけるためにグラフをトラバースするために必要なコードはそれほど難しくありません。これらの統計が何であるかがソリューションを推進するはずです。
ノードIDを選択するためのMySQLクエリのパフォーマンスについてコメントすることはできません。それは、選択する必要のあるノードの数とインデックス作成戦略に帰着すると思います。ただし、グラフのトラバースに関しては、パフォーマンスの側面については同意します。
これはまさにこれに関する良い記事です: 大規模グラフトラバーサルでのMySQLとNeo4j そしてこの場合、彼らが大きいと言うとき、それらは100万の頂点/ノードと400万のエッジのみを意味します。したがって、それは特に密なグラフでさえありませんでした。
リレーショナルデータベースはグラフ構造を処理できます。それらのいくつかは、それらを適度にエレガントに処理することさえできます(リレーショナルデータベースが取得するのと同じくらいエレガントです!)。
リレーショナルデータベースでの一般的なグラフ処理の鍵は 再帰的な共通テーブル式 (RCTE)です。これにより、基本的に、組み合わせることにより、行のセットに対してクエリを繰り返し(再帰的にではなく)展開できます。行のルートセットを選択するクエリと、これまでに選択された行の隣接を定義するクエリ。構文は少し不格好ですが、一般的で強力です。
RCTEは、PostgreSQL、Firebird、SQL Server、そして明らかにDB2でサポートされています。 Oracleには、異なるが同等の構成があります。最近のバージョンは適切なRCTEをサポートしていることを読みました。 MySQLはRCTEをサポートしていません。 MySQLに慣れていない場合は、基本的にはるかに優れたデータベースであるPostgreSQLの使用を検討することをお勧めします。
ただし、一般的なグラフをサポートする必要はなく、ツリーだけをサポートする必要があるようです。その場合、より具体的なオプションがあります。
1つは古典的ですが、かなり気が遠くなるような 入れ子集合 です。
より簡単な方法は、各行にパスを格納することです。これは、ツリー内の行の位置を表す文字列であり、ノードのパスが任意のサブノードのパスのプレフィックスであるというプロパティがあり、非常に効率的に使用できます。祖先に関するさまざまなクエリを実行します(「ノードAはノードBの子ですか?」、「ノードAとノードBの最も低い共通の祖先は何ですか?」など)。たとえば、ルートからツリーをウォークし、途中で検出された行のIDをスラッシュで結合することにより、行のパスを作成できます。これは構築が簡単ですが、ツリーを再配置する場合は維持するように注意してください。パス列を使用すると、and path like '23/%'
を追加するだけで、クエリを特定のツリーに制限できます。ここで、23
はルートのIDです。
したがって、グラフデータベースはおそらくグラフデータを格納およびクエリするための最良の方法ですが、それが唯一のオプションではありません。すべてのデータを単一のデータベースに含めることの利点と、グラフデータベースを使用することの利点を比較検討することをお勧めします。
私は主にBinaryNerdを使用していますが、バリエーションを追加したいと思います。ライブデータをNeo4jに保存してから、統計/レポートに必要なデータを抽出してMySQLに入れることができます。検索の場合は、必要に応じて Neo4j-Lucene統合 を使用します。
INを使用すると、クエリを改善できます。
SELECT *
FROM items
WHERE item_id IN (45, 345435, 343, 78, 4522, 676, 443, 4255, 4345)
また、リレーショナルデータベースがツリー構造の格納に苦手であることも完全には真実ではありません。確かに、MySQLにはそれを簡単にするいくつかの機能が欠けていますが、他のほとんどのデータベースはそれをうまくサポートしています。 OracleにはCONNECT BY
。主流のRDBMSのほとんどには、何らかの形の再帰クエリがあります。MySQLは注目すべき例外です。おそらく、PostgreSQLを見て、それがニーズを満たしているかどうかを確認できますか?