Korzystanie z Neo4j 1.9.9. Niektóre zapytania Cyphera, które prowadziliśmy, wydawały się nieuzasadnione powolne. Niektóre Dochodzenie wykazało, że:Neo4j 1.9.9 starszy indeks bardzo wolno po usunięciu
Usuń 200k węzły trwa około 2-3 sekund na moim sprzęcie (MacBook Pro), kiedy je wybrać za pomocą:
START n=node(*) DELETE n
Dodawanie WHERE nie wpływa znacząco zwolnij go
Jeśli węzły zostały wybrane przy użyciu indeksu, ma podobną wydajność, np.
START n=node:__types__(className="com.e2sd.domain.Comment") DELETE n
wyjątkiem że kiedy powtórzenie poprzedniego testu, to 20x lub więcej wolniej, z rzeczywistego czasu waha się od 80 do kilkuset sekund. Co ciekawe, nie ma znaczenia, czy powtórzę test w tej samej maszynie JVM, czy uruchomę nowy program, czy wyczyści wszystkie węzły w bazie danych i zweryfikuję, że ma zero węzłów. Indeks oparte kasowania jest bardzo powolny w dowolnym późniejszym przebiegu testu aż I sprać mój katalog danych neo4j z
rm -R target/neo4j-test/
Podam kilka przykładów kodu Scala tutaj. Z przyjemnością dostarczę więcej szczegółów w razie potrzeby.
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")
}
}
Używamy tutaj Neo4j z następującą konfiguracją 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.*"/>
Dlaczego zapytanie DELETE jest powolne w opisanych warunkach?
Myślę, że musisz wyraźnie usunąć wpisy z indeksu starszego typu, nie wiesz, czy wystarczy usunąć węzeł. Tak więc, po uruchomieniu go po raz drugi, masz 400k wpisów w indeksie, mimo że połowa z nich wskazuje na usunięcie węzłów. W ten sposób program jest powolny, ponieważ wielokrotne uruchamianie rozszerza rozmiar indeksu. –
To całkiem dobra hipoteza --- nie przyszło mi do głowy, że usunięcie węzła w milczeniu pozostawiłoby wiszące odniesienia w indeksie, ale biorąc pod uwagę inne zachowanie, które ma sens! –
Jeśli utworzysz odpowiedź, przetestuję tę hipotezę i przyznaję nagrodę, jeśli jest poprawna. Musisz się pośpieszyć, wkrótce straci ważność. –