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?
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. –
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! –
Se scrivi una risposta, verificherò quest'ipotesi e assegnerò la taglia se corretta. Dovrai comunque sbrigarti, scade presto. –