2016-11-14 8 views
0

私はノードのセットを持っています。私は距離と呼ばれる関係で各単語を他のすべての単語に結びつけたい。私は次のクエリを実行します:Neo4j Cypher最適化デカルト積の各ノード間の関係を作成します

 
match (word1:Word) 
with word1 
match (word2:Word) 
where word1 <> word2 
merge (word1)-[distance:DISTANCE ]->(word2) 
return word1, distance, word2 

これは永遠に実行されます。 〜600ノードしかありませんが、600 * 600の関係が期待されますが、クエリは2時間実行しないでください。 JavaではNeo4jよりも速いです。それをもっと早くするためにはどんなアドバイスが必要ですか?私はすでにプロパティの1つにインデックスを追加しており、改善されていません。

+1

これは、1回のトランザクションで作成された360Kのリレーションシップで、メモリ設定によって大きく異なる可能性があります。 –

+1

また、360Kの行を戻していることに注意してください。少なくとも、あなたがそれを必要としないように見えるので、あなたのリターンを排除することができます。また、DISTANCE関係に変数を追加する必要はありません。クエリでこれ以上何もしない場合は、マージをバッチアップする必要がある場合は、APOCライブラリプロシージャapoc.periodic.commit()を試してください。 – InverseFalcon

答えて

3

いくつかの所見:

  1. あなたのクエリは、単一のトランザクションで2 * 600 * 599(または718800)MERGE操作を実行しようとします。 2の理由は、すべての単語のペア(x​​とyなど)が2回(x/yとy/xとして)表示されるためです。あなたは(おそらく)半分の操作しか実行したくないでしょう。
  2. x/yとy/xの振る舞いによって、単語のペアごとに2つの方向(1つずつ)が存在することを確認します。それはあなたが望む(または必要な)関係の数の(おそらく)倍の数です。
  3. 単一トランザクションで720K(またはさらに360K)の操作を実行しようとすると、DBサーバーのメモリが不足する可能性があります。

上記の問題を修正する可能性のある変更されたクエリです。 ID(w1) < ID(w2)テストでは、ペア内の2語が同じでなく、同じペアが1回だけ処理されることを確認します。また、APOC手順apoc.periodic.iterateを使用して、別々のトランザクションで同時に10Kリレーションシップを作成します。

CALL apoc.periodic.iterate(
    'MATCH (w1:Word), (w2:Word) WHERE ID(w1) < ID(w2) RETURN w1, w2', 
    'CREATE (w1)-[:DISTANCE]->(w2)', 
    {batchSize:10000, parallel:true}) YIELD batches, total 
RETURN * 

注1:このクエリを使用すると、DBのいずれかのDISTANCE関係なしに開始することを前提としていますので、代わりにMERGEの安いCREATE句を使用しています。 DISTANCEの関係が既に存在する場合は、代わりにMERGEを使用します(ただし、最初の関係が反対の場合は、同じペアの間に2番目の関係が作成される可能性があります)。

注2:新しいCypherコードでは問題2が不可能なため、バッチを並行して実行することは安全です。 2つのトランザクションが同じ2つのノード間で逆方向の関係を同時に作成しようとすると、deadlockという結果になり、少なくとも1つのトランザクションが失敗する可能性があります。

注3:このクエリでは、最初のステートメント(MATCH句付き)は、メモリ不足または処理に時間がかかりすぎないと仮定しています。その前提が間違っている場合は、適切に変更されたクエリを使用してapoc.periodic.commitを使用すると効果があります。

+0

助けてくれてありがとう。私はその質問を試しました。それは30分で実行されます。それは確かに遅いです。 :( – bobby

関連する問題