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.
Wie lange dauert es? (Haben Sie eine Schätzung, wenn keine tatsächliche Zeit?) –