2015-03-03 6 views
5

Uso di Neo4j 1.9.9. Alcune query di Cypher che stavamo eseguendo sembravano essere irragionevolmente lente. Alcuni inchiesta ha dimostrato che:Indice legacy Neo4j 1.9.9 molto lento dopo l'eliminazione

  • Elimina 200k nodi dura circa 2-3 secondi sul mio hardware (MacBook Pro), quando seleziono utilizzando:

    START n=node(*) DELETE n 
    
  • L'aggiunta di una clausola WHERE non lo fa in modo significativo rallentarlo

  • Se i nodi sono stati selezionati utilizzando un indice, ha prestazioni simili, ad esempio

    START n=node:__types__(className="com.e2sd.domain.Comment") DELETE n 
    
  • Salvo che quando viene ripetuta la prova precedente, è 20x o più lento, con il tempo effettivo variabile da 80 a diverse centinaia di secondi. Ancora più curioso, non importa se ripeto il test nella stessa JVM o avvio un nuovo programma, o cancelli tutti i nodi nel database e verifichi che abbia zero nodi. L'indice a base di eliminazione è estremamente lento su ogni successiva esecuzione del test fino ho Clobber mia directory dei dati Neo4j con

    rm -R target/neo4j-test/ 
    

darò qualche esempio di codice Scala qui. Sono felice di fornire maggiori dettagli, come richiesto.

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") 
    } 
} 

Stiamo utilizzando Neo4j incorporato qui con la seguente configurazione Spring Data.

<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.*"/> 

Perché la query DELETE è lenta nelle condizioni descritte?

+0

Penso che sia necessario eliminare in modo specifico le voci dall'indice legacy, non è sicuro che eliminare il nodo sia sufficiente. Quindi, quando lo esegui la seconda volta, hai 400k voci nel tuo indice, anche se la metà di esse punta a nodi cancellati. In questo modo il tuo programma è lento poiché le esecuzioni ripetute estendono la dimensione dell'indice. –

+0

Questa è un'ipotesi piuttosto buona --- non mi è venuto in mente che l'eliminazione del nodo avrebbe lasciato silenziosamente i riferimenti sospesi nell'indice, ma dato l'altro comportamento che ha senso! –

+0

Se scrivi una risposta, verificherò quest'ipotesi e assegnerò la taglia se corretta. Dovrai comunque sbrigarti, scade presto. –

risposta

2

È necessario eliminare in modo specifico le voci dall'indice precedente, l'eliminazione dei nodi non è sufficiente per rimuoverla da un indice legacy. Quindi, quando lo esegui la seconda volta, hai 400k voci nel tuo indice, anche se la metà di esse punta a nodi cancellati. In questo modo il tuo programma è lento poiché le esecuzioni ripetute estendono la dimensione dell'indice.

Ho avuto questo problema quando ho scritto un'estensione su neo4j spaziale per caricare in massa RTree. Ho dovuto usare l'API Java che dovevi eliminare esplicitamente dall'indice separatamente dall'eliminazione del nodo. Sono contento di poterti aiutare.

+0

Ho usato index.query ("*: *") come suggerito in alcune altre pagine StackOverflow per ottenere tutti i nodi nell'indice, quindi eliminato ognuno, quindi continuato aggiungendo ogni nodo con un tipo nuovamente all'indice. –