2015-03-03 3 views
5

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?

+0

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. –

+0

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! –

+0

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. –

Antwort

2

Sie müssen Einträge aus dem Legacy-Index löschen, das Löschen von Knoten reicht nicht aus, um einen Legacy-Index zu entfernen. 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.

Ich hatte dieses Problem, als ich eine Erweiterung zu Neo4j räumlichen schrieb, um den RTree in großen Mengen zu laden. Ich musste die Java-API verwenden, die Sie explizit aus dem Index löschen mussten, um den Knoten zu löschen. Froh, dass ich helfen konnte.

+0

Ich habe index.query ("*: *") wie in einigen anderen StackOverflow-Seiten vorgeschlagen verwendet, um alle Knoten im Index zu erhalten, und löschte sie dann. Anschließend fügte man jeden Knoten mit einem Typ zurück zum Index hinzu. –