2015-03-03 18 views
5

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 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?

+0

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

+0

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

+0

Jeśli utworzysz odpowiedź, przetestuję tę hipotezę i przyznaję nagrodę, jeśli jest poprawna. Musisz się pośpieszyć, wkrótce straci ważność. –

Odpowiedz

2

Musisz wyraźnie usunąć wpisy z indeksu starszego typu, usunięcie węzłów nie jest wystarczające, aby usunąć go z indeksu starszego typu. 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.

Miałem ten problem, gdy napisałem rozszerzenie do neo4j przestrzenne, aby załadować luzem RTree. Musiałem użyć interfejsu API Javy, który musiałeś jawnie usunąć z indeksu, niezależnie od usuwania węzła. Cieszę się, że mogłem pomóc.

+0

Użyłem index.query ("*: *") zgodnie z sugestią w niektórych innych stronach StackOverflow, aby uzyskać wszystkie węzły w indeksie, a następnie usunąć każdy z nich, a następnie kontynuować dodając każdy węzeł z typem z powrotem do indeksu. –