Verwenden von Neo4j 1.9.9. Einige Cypher-Abfragen, die wir ausgeführt haben, schienen unangemessen langsam zu sein. Einige Untersuchungen zeigten, dass:Neo4j 1.9.9 Legacy-Index sehr langsam nach Löschungen
löschen 200k Knoten dauert etwa 2-3 Sekunden auf meiner Hardware (MacBook Pro), wenn ich sie mit auswählen:
START n=node(*) DELETE n
Hinzufügen einer WHERE-Klausel nicht wesentlich verlangsamen
Wenn die Knoten mit einem Index ausgewählt wurden, hat es eine ähnliche Leistung, z
START n=node:__types__(className="com.e2sd.domain.Comment") DELETE n
Außer dass, wenn die vorherigen Test wiederholen, es 20x oder mehr langsamer, mit der tatsächlichen Zeit von 80 bis mehreren 100 Sekunden variiert. Noch neugieriger ist es nicht, ob ich den Test in derselben JVM wiederhole oder ein neues Programm starte oder alle Knoten in der Datenbank lösche und verifiziere, dass es keine Knoten hat. Der Index-basierte löschen ist extrem langsam auf jedem nachfolgenden Durchlauf des Tests bis ich mit meinem Neo4j Datenverzeichnis clobber
rm -R target/neo4j-test/
Ich werde einig Beispiel Scala Code hier geben. Ich bin glücklich, mehr Details zur Verfügung zu stellen, wie erforderlich.
for (j <- 1 to 3) {
log("Total nodes in database: " + inNeo4j(""" START n=node(*) RETURN COUNT(n) """).to(classOf[Int]).single)
log("Start")
inNeo4j(""" CREATE (x) WITH x FOREACH(i IN RANGE(1, 200000, 1) : CREATE ({__type__: "com.e2sd.domain.Comment"})) """)
rebuildTypesIndex()
log("Created lots of nodes")
val x = inNeo4j(
"""
START n=node:__types__(className="com.e2sd.domain.Comment")
DELETE n
RETURN COUNT(n)
""").to(classOf[Int]).single
log("Deleted x nodes: " + x)
}
// log is a convenience method that prints a string and the time since the last log
// inNeo4j is a convenience method to run a Cypher query
def rebuildTypesIndex(): Unit = {
TransactionUtils.withTransaction(neo4jTemplate) {
log.info("Rebuilding __types__ index...")
val index = neo4jTemplate.getGraphDatabase.getIndex[Node]("__types__")
for (node <- GlobalGraphOperations.at(neo4jTemplate.getGraphDatabaseService).getAllNodes.asScala) {
index.remove(node)
if (node.hasProperty("__type__")) {
val typeProperty = node.getProperty("__type__")
index.add(node, "className", typeProperty)
}
}
log.info("Done")
}
}
Wir verwenden Neo4j hier mit der folgenden Spring Data-Konfiguration eingebettet.
<bean id="graphDbFactory" class="org.neo4j.graphdb.factory.GraphDatabaseFactory"/>
<bean id="graphDatabaseService" scope="singleton" destroy-method="shutdown"
factory-bean="graphDbFactory" factory-method="newEmbeddedDatabase">
<constructor-arg value="target/neo4j-test"/>
</bean>
<neo4j:config graphDatabaseService="graphDatabaseService" base-package="my.package.*"/>
Warum ist die DELETE-Abfrage unter den beschriebenen Bedingungen langsam?
Ich denke, dass Sie Einträge aus dem Legacy-Index löschen müssen, nicht sicher, dass das Löschen des Knotens ausreicht. Wenn Sie es also das zweite Mal ausführen, haben Sie 400.000 Einträge in Ihrem Index, obwohl die Hälfte auf gelöschte Knoten verweist. Auf diese Weise ist Ihr Programm langsam, da wiederholte Läufe die Größe des Indexes erweitern. –
Das ist eine ziemlich gute Hypothese - es ist mir nicht in den Sinn gekommen, dass das Löschen des Knotens stillhängende Referenzen im Index hinterlassen würde, aber angesichts des anderen Verhaltens, das Sinn macht! –
Wenn Sie eine Antwort einreichen, werde ich diese Hypothese testen und das Kopfgeld vergeben, wenn es korrekt ist. Sie müssen sich beeilen, es läuft bald ab. –