2017-05-04 3 views
0

Ich habe rund 800k Knoten und ich versuche, rund 8 Millionen Kanten in Neo4j Enterprise Edition mit Neo4j .Net-Client einfügen.Edge Creation zu langsam bei Verwendung von Neo4j .Net Client

Ich mache so etwas und dieser Prozess ist wirklich langsam. Versuchte Neo4j-Treiber, aber das ist auch langsam. Ich habe auch das Namensfeld indiziert. Könnte jemand bitte eine alternative Methode zur schnelleren Erstellung von Kanten vorschlagen?

public static async Task AddEdges(List<Edge> edgeTable, IGraphClient client) 
{ 

     try 
     { 
      foreach (var item in edgeTable) 
      { 
       await client.Cypher 
       .Match("(parentNode:MyNodeType)", "(childNode:MyNodeType)") 
       .Where((MyNodeType parentNode, MyNodeType childNode) => parentNode.Name == item.SourceName && childNode.Name==item.MemberName) 
       .Create("(childNode)-[:belongsTo]->(parentNode)") 
       .ExecuteWithoutResultsAsync(); 
      } 

     } 
     catch (Exception ex) 
     { 
      //ex handling 
     } 


} 
+0

Wie lange dauert es? (Haben Sie eine Schätzung, wenn keine tatsächliche Zeit?) –

Antwort

0

Sie await verwenden jede async Anfrage zu drehen (aufgrund Ihrer Verwendung von ExecuteWithoutResultsAsync) in eine synchrone Anforderung. Das bedeutet, dass die aktuelle http-Anfrage antworten muss, bevor die nächste gesendet werden kann, obwohl Sie sich nicht um die Antworten kümmern. (Übrigens, um das Gleiche zu erreichen, hätten Sie einfach ExecuteWithoutResults ohne await verwenden können.) Diese Art der Serialisierung sollte nach Möglichkeit vermieden werden. In Ihrem Anwendungsfall besteht jedoch die Möglichkeit von Deadlocks mit paralleler Ausführung (aufgrund der Schreibsperre der Endknoten beim Erstellen neuer Beziehungen).

Außerdem führen Sie nur eine einzige CREATE Operation in jeder Transaktionsanforderung aus. Das bedeutet, dass Sie 8 Millionen serialisierte Transaktionsanforderungen stellen. Natürlich wird das langsam sein.

Eine Lösung, die einen gewissen asynchronen Betrieb ermöglicht und gleichzeitig Deadlock vermeidet, wäre die Analyse Ihrer Daten (idealerweise programmgesteuert), um Gruppen von Kanten zu erstellen, die keine überlappenden Knoten mit anderen Gruppen haben. Auch wenn die Kanten innerhalb einer Gruppe noch synchron bearbeitet werden müssen, können verschiedene Gruppen parallel ohne Deadlocks bearbeitet werden.

Wenn Sie Ihre Operationen an den N Kanten innerhalb einer Gruppe in einer einzigen Transaktion ausführen können, vermeiden Sie den Overhead für die Ausführung von N synchronen Transaktionsanforderungen für diese Gruppe, und die oben erwähnten Deadlocks werden ebenfalls vermieden.

Mithilfe der UNWIND-Klausel können Sie Operationen über die Daten aus einer Liste in einer einzelnen Anforderung iterieren. So etwas wie das Folgende sollte funktionieren. Beachten Sie, dass die edgeTable Eingabeliste der Kanten von einer einzelnen Gruppe enthalten muss, wie oben beschrieben:

public static async Task AddEdges(List<Edge> edgeTable, IGraphClient client) { 
    try { 
     client.Cypher 
      .Unwind(edgeTable, "item") 
      .Match("(parentNode:MyNodeType)", "(childNode:MyNodeType)") 
      .Where((MyNodeType parentNode, MyNodeType childNode) => parentNode.Name == item.SourceName && childNode.Name==item.MemberName) 
      .Create("(childNode)-[:belongsTo]->(parentNode)") 
      .ExecuteWithoutResultsAsync(); 
    } catch (Exception ex) { 
     //ex handling 
    } 
} 

Beachten Sie, dass ich ExecuteWithoutResultsAsync verwende ohne await, so dass die Gruppen asynchron verarbeitet werden.

Ein Vorbehalt ist jedoch, dass Sie den Neo4j-Server nicht bitten, zu viel auf einmal zu verarbeiten, damit es nicht über genügend Arbeitsspeicher verfügt. Wenn also eine Gruppe zu groß ist oder wenn zu viele Gruppen gleichzeitig verarbeitet werden, sollten Sie die Rate, mit der Sie AddEdges aufrufen, drosseln und/oder große Gruppen in kleinere Blöcke aufteilen und sicherstellen, dass diese Blöcke sind synchron zueinander verarbeitet werden.

Verwandte Themen