2017-07-03 8 views
2

あまりにも具体的すぎることなく、私はNeo4j 3.2のCyperに次の問題に直面しています。 User、Comment、Likeの3つのエンティティを持つデータベースがあるとします。何らかの理由でNeo4j 3.2 Cypher低性能

、私は次のクエリを実行しようとしています:

MATCH (n:USER) WHERE n.name = "name" 
WITH n 
MATCH (o:USER) 
WITH n, o, "2000" as number 
MATCH (n)<-[:CREATED_BY]-(:COMMENT)-[:HAS]->(l:LIKE)-[:CREATED_BY]->(o) 
RETURN n, o, number, count(l) 

クエリが完了するまでに数分かかります。しかし、の部分として"2000"を単に削除すると、数十ミリ秒以内に完了します。

なぜ誰かが説明をしていますか?

編集: "2000"の数字は部分です。底なし、それなし。

+1

私の想定では、you/cypherは32969個の新しい文字列を作成します。あなたはJVMでgc休止を打つのですか?番号2000を使用しても同じことが起こっていますか? – manonthemat

答えて

4

あなたは(そう、特定の名前の最初の試合は遅いです)今のあなたは、インデックスを使用していない、あなたのクエリをクリーンアップする必要があるとしている、とあなたはデカルトを行いますproduct against all:ユーザーノード。次に、各行の文字列を作成します。

まず、開始ノードを高速に見つけるために、USER(name)にインデックスを作成します。

その後、残りの試合をクリーンアップする必要があります。

代わりにこのような何かを試してみてください:

MATCH (n:USER) WHERE n.name = "name" 
WITH n, "2000" as number 
MATCH (n)<-[:CREATED_BY]-(:COMMENT)-[:HAS]->(l:LIKE)-[:CREATED_BY]->(o:User) 
RETURN n, o, number, count(l) 

をあなたが「2000」せずに、クエリのように、このクエリを使用して同様のプランが表示されます。

oにマッチするデカルト商品がありますが、最後の試合のパターンで発生しなければならないという点で、oの追加の制限があることに気づくほど、インテリジェントになっていますその状況に対するその最適化により、デカルト積を実行することを避けることができます。

しかし、新しい変数numberの導入により、プランナはこれが基本的に同じ状況であることを認識できなくなり、プランナはデカルト積を最適化しませんでした。

今のところ、クエリの実行方法を明示し、クエリ内のデカルト積を避けるようにしてください。 、それは代わりにあなたの結果のすべての行のためにそれを後で試合でユーザー言っている:この特定のケースでは、それはあなたが3行目のMATCH (o:User)を持っている場合、それはoの種類があることを宣言していないことを理解することが重要

をですこれまでのところ、すべてのユーザーに対してデカルト製品を実行してから、ユーザーノードごとに、提供されたパターン内にどのノードが存在するかを確認します。これは、提供されたパターンを単純に拡張して、パターンの反対側にあるユーザーノードを見つけることと比べて、多くの不必要な作業です。

EDIT

限り、両方の取得など:LIKEや:嫌いノード数は、おそらくこのような何かを試してみてください。

MATCH (n:USER) WHERE n.name = "name" 
WITH n, "2000" as number 
MATCH (n)<-[:CREATED_BY]-(:COMMENT)-[:HAS]->(likeDislike)-[:CREATED_BY]->(o:User) 
WITH n, o, number, head(labels(likeDislike)) as type, count(likeDislike) as cnt 
WITH n, o, number, CASE WHEN type = "LIKE" THEN cnt END as likeCount, CASE WHEN type = "DISLIKE" THEN cnt END as dislikeCount 
RETURN n, o, number, sum(likeCount) as likeCount, sum(dislikeCount) as dislikeCount 

あなたはまだそのnumber変数であり必要と仮定。

+0

あなたの答えに感謝します。これはいくつかのことを明確にします。しかし、そのような質問を書く理由は、3行目が単に他のすべてのユーザーにマッチする以上のことをするということでした。この例では、データベースにDISLIKEノードがあるとしますが、これは設計フローです。クエリは、nと他のすべてのoとの間のDISLIKEノードの数をカウントし、nと他のすべてのoとの間のすべてのLIKEノードもカウントする必要があります。 – user3455402

+2

ここでもデカルト積を実行するのは良い理由ではありませんが、2種類のノードをチェックしなければならない場合、問題は悪化します。すべてのシングルのパターンをチェックする理由はありません:ユーザー。代わりに、パターン自体によってどのユーザーが検出されたかを確認するだけです。 DISLIKEユースケースでは、LIKEまたは:DISLIKEノードにラベルを付けないほうが簡単でしょう。次に、CASEを使用してそれぞれのカウントを取得します。 – InverseFalcon