2012-03-05 19 views
5

Chcę przechowywać niektóre dane w mojej bazie danych neo4j. używam do tego danych sprężynowych-neo4j.metoda zapisu CRUDRepository jest bardzo powolna?

mój kod jest jak następuje:

for (int i = 0; i < newRisks.size(); i++) { 
     myRepository.save(newRisks.get(i)); 
     System.out.println("saved " + newRisks.get(i).name); 
    } 

Moja newRisks-tablica zawiera około 60000 i 60000 krawędziach obiektów. Każdy węzeł i krawędź ma jedną właściwość. Czas trwania tej pętli wynosi około 15 - 20 minut, czy to normalne? Użyłem Java VisualVM do wyszukiwania niektórych wąskich gardeł, ale moje średnie użycie procesora było 10 - 25% (z 4 rdzeni), a mój stert był mniej niż w połowie pełny.

Czy są jakieś opcje, aby zwiększyć tę operację?


EDIT: dodatkowy jest na pierwszym wezwaniu myRepository.save(newRisks.get(i)); JVM spada assleep FPR kilka minut przed pierwszym wyjściem nadchodzi

Druga Edycja:

Ryzyko Klasa:

@NodeEntity 
public class Risk { 
    //... 
    @Indexed 
    public String name; 

    @RelatedTo(type = "CHILD", direction = Direction.OUTGOING) 
    Set<Risk> risk = new HashSet<Risk>(); 

    public void addChild(Risk child) { 
     risk.add(child); 
    } 

    //... 
} 

Tworzenie ryzyka:

@Autowired 
private Repository myRepository; 

@Transactional 
public Collection<Risk> makeSomeRisks() { 

    ArrayList<Risk> newRisks = new ArrayList<Risk>(); 

    newRisks.add(new Risk("Root")); 

    for (int i = 0; i < 60000; i++) { 
     Risk risk = new Risk("risk " + (i + 1)); 
     newRisks.get(0).addChild(risk); 
     newRisks.add(risk); 
    } 

    for (int i = 0; i < newRisks.size(); i++) { 
     myRepository.save(newRisks.get(i)); 
    } 

    return newRisks; 
} 
+0

Zgodnie z [dokumentacją] (http://static.springsource.org/spring-data/data-neo4j/docs/2.0.0.RC1/api/org/springframework/data/neo4j/repository/CRUDRepository. html), CRUDRepository.save może przyjąć Iterable jako argument. Dlaczego nie tylko myRepository.save (newRisks)? – Thomas

+0

Próbowałem tego i działa również. ale nie jest szybszy. więc widzę, że on nie jest martwy ^^ – hilbert

+0

czy mógłbyś pokazać strukturę swojej klasy i dowolne węzły-encje i encje-relacje, do których się odnosi. A metoda budowy twoich instancji Risk? –

Odpowiedz

5

Problem polega na tym, że robisz mass-inserty z interfejsem API, który nie jest do tego przeznaczony.

Tworzysz ryzyko i 60k dzieci, najpierw zachowujesz root, który jednocześnie utrzymuje dzieci w wieku 60 tys. (I tworzy relacje). Dlatego pierwsza oszczędność trwa tak długo. A potem znowu ratujesz dzieci.

Istnieje kilka sposobów na przyspieszenie pracy z SDN.

  1. nie używać podejścia do masowego zbierania wkładek, utrzymują się zarówno uczestników i użyć template.createRelationshipBetween (root, dziecko, "dziecko", false);

  2. utrzymują dzieci najpierw następnie dodać wszystkie utrzymywały dzieci do obiektu głównego i utrzymują, że

  3. Jak to zrobiłeś, użyj Neo4j-core API ale zadzwonić template.postEntityCreation (węzeł, Risk.class) tak że możesz uzyskać dostęp do jednostek za pośrednictwem SDN.Następnie musisz również indeksować encje na swoim własnym (db.index.forNodes ("Risk"). Add (node, "name", name);) (lub użyj auto-index neo4j core-api, ale to nie jest kompatybilny z SDN).

  4. Niezależnie z podstawowej API lub SDN należy użyć TX-rozmiary około 10-20k węzłów/RELS dla uzyskania najlepszej wydajności

+0

dzięki, masz rację. Po pierwsze, po prostu zapiszę root, zajmuje to tylko 6 minut. Może później muszę wypróbować inne proponowane przez ciebie rozwiązania. – hilbert

1

Czy wkładki do twojej bazy danych (poza Javą) mają takie samo opóźnienie lub czy jest to problem tylko przez dane sprężyny?

+0

dobry pomysł, ale jak mogę wstawić tę liczbę notatek itp. Z java? nie chcę brać innego języka programowania. Inna idea: mogę spróbować użyć standardowego neo4j java api, a nie danych źródłowych-neo4j. – hilbert

+0

Po prostu wywołaj instrukcję wstawiania w wybranym edytorze SQL. To sprawdzi szybkość samej bazy danych, poza jakimkolwiek językiem programowania. – abehrens

+0

jego baza danych noSQL, ale próbowałem go z natic api java dla neo4j, thats szybciej – hilbert

5

Chyba znalazłem rozwiązanie:

Próbowałem samą wkładkę używając Nativ neo4j Java API:

GraphDatabaseService graphDb; 
Node firstNode; 
Node secondNode; 
Relationship relationship; 

graphDb = new EmbeddedGraphDatabase(DB_PATH); 
Transaction tx = graphDb.beginTx(); 

try { 
    firstNode = graphDb.createNode(); 
    firstNode.setProperty("name", "Root"); 

    for (int i = 0; i < 60000; i++) { 
     secondNode = graphDb.createNode(); 
     secondNode.setProperty("name", "risk " + (i+1)); 

     relationship = firstNode.createRelationshipTo(secondNode, RelTypes.CHILD); 
    } 
    tx.success(); 
} 
finally { 
    tx.finish(); 
    graphDb.shutdown(); 
} 

wynik: po kilku sconds, baza danych jest wypełniona ryzyka .

Być może odbicia spowalniają tę rutynę za pomocą danych sprężynowych - neo4j. @ Michael Głód mówi coś takiego w swojej książce GoodRelationships, dzięki za wskazówkę.

+0

to uratowało mój dzień! bardzo doceniane, dzięki. – jarandaf

1

I w obliczu tego samego problemu jak OP. Naprawdę przydatna w moim przypadku była zmiana trybu Neo4j z trybu zdalny serwer na osadzony. Dobry przykład osadzonego użycia SDN można znaleźć here.

Powiązane problemy