約100Kのノードと200Kのリレーションを持つ進化プロセスを表すNeo4Jデータベースがあります。ノードは世代の個人であり、エッジは親子関係を表します。主な目標は、最終世代で関心のある1つまたは複数のノードを取得し、それらの進化の歴史を調査できるようにすることです(大まかに言うと、「どうやってここにたどり着いたのですか?」)。
すべての祖先を見つけるための「明白な」最初のクエリは、そのスペースを通る可能な祖先とパスが多すぎるため、機能しません。
match (a)-[:PARENT_OF*]->(c {is_interesting: true})
return distinct a;
そのため、データを前処理して、一部のエッジが「特別」としてマークされ、ほとんどすべてのノードが最大で1つの「特別」親エッジを持つようにしましたが、両方の親エッジが「特別」としてマークされることもあります。したがって、私の希望は、このクエリが「特別な」エッジに沿って(ほぼ)一意のパスを(効率的に)生成することでした。
match (a)-[r:PARENT_OF* {special: true}]->(c {is_interesting: true})
return distinct a;
ただし、これはまだ実行不可能なほど遅いです。
「人間として」のロジックは単純であるため、これは苛立たしいことです。少数の「興味深い」ノード(多くの場合、1、数十を超えない)から開始し、ほとんど常に固有の「特別な」エッジに沿って追跡します。2つの「特別な」親を持つノードの数が非常に少ないと仮定すると、これはO(N)のようになります。ここで、Nは過去の世代数です。
ただし、Neo4Jでは、すべてのステップが一意である一意の「興味深い」ノードから25ステップ戻るには、30秒かかります。また、分岐が1つになると(両方の親が「特別」である場合)、ステップの機能。28ステップ(最初の分岐点に到達)は2分、30ステップ(まだ1つの分岐点しかない)は6分かかり、シミュレーションの開始まで100ステップすべてを試すことすら考えていません。
昨年の同様の作業のいくつかはパフォーマンスが向上したように見えましたが、エッジにデータフィールドを使用する代わりに、さまざまなエッジラベル((a)-[:SPECIAL_PARENT_OF*]->(c)
およびなど(a)-[:PARENT_OF*]->(c)
)を使用しました。関係フィールドの値を照会するのは良い考えではありませんか?このモデルの関係にはかなりの数の異なる値(ブール値、数値)が関連付けられており、それらを使用して検索を効率的に制限できることを期待/想定していましたが、実際にはそうではなかった可能性があります。
モデルやクエリを調整する方法についての提案をいただければ幸いです。
私が言及すべきアップデート、これはすべてNeo4J2.1.7で行われます。Brian Underwoodの提案に従って、2.2を試してみて、報告します。
Neo4J 2.2のプロファイリングツールで物事を調査した後(ヒントについてはBrian Underwoodに感謝します)、Neo4Jがエッジプロパティで事前フィルタリングを行わないことはかなり明らかです。これにより、長いパスで厄介な組み合わせ爆発が発生します。 。
たとえば、元のクエリ:
match (a)-[r:PARENT_OF* {special: true}]->(c {is_interesting: true})
return distinct a;
見つかったすべてのパスをa
するc
と、その後でないエッジを持っているものを排除special
。からa
へのパスは数百万あるためc
、これは完全に実行不可能です。
私が代わりに追加する場合IS_SPECIAL
があった場所にエッジをPARENT_OF
持っていたエッジ{special: true}
、その後、クエリは、私が第二の下で約100世代をプッシュバックすることができ、本当に速いなります。
このクエリは、すべての新しいエッジを作成します。
match (a)-[r:PARENT_OF {special: true}]->(b)
create (a)-[:IS_SPECIAL]->(b);
グラフに91Kの関係を追加するのに1秒もかかりません。
次に
match (c {is_interesting: true})
with c
match (a)-[:IS_SPECIAL*]->(c)
return distinct a;
一意のターゲットノードから戻る「特別な」パスに沿って112ノードを見つけるのに1秒もかかりませんc
。Neo4Jはノードのプロパティを事前にフィルタリングしていないようであり、複数の「興味深い」ターゲットノードがある場合は処理が非常に遅くなるため、c
最初に一致させ、使用with c
するノードのセットを制限することも重要です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加