Optymalizacja wstawiania partii o dużej objętości do Neo4j za pomocą REST

Muszę wstawić ogromną liczbę węzłów z relacjami między nimi do Neo4j poprzez punkt końcowy wsadowy API REST, około 5k rekordów / s (wciąż rośnie).

Będzie to ciągłe wstawianie 24x7. Każdy rekord może wymagać utworzenia tylko jednego węzła, ale inny może wymagać dwóch węzłów i utworzenia jednej relacji.

Czy mogę poprawić wydajność wkładek, zmieniając procedurę lub modyfikując ustawienia Neo4j?

Moje dotychczasowe postępy:

1. Testowałem z Neo4j przez chwilę, ale nie mogłem uzyskać wydajności, której potrzebowałem

Pole serwera testowego: 24 rdzenie + 32 GB pamięci RAM

Neo4j 2.0.0-M06 zainstalowany jako samodzielna usługa.

Uruchamianie mojej aplikacji Java na tym samym serwerze (aplikacja Neo4j i Java będą musiały w przyszłości działać na własnym serwerze, więc nie można używać trybu osadzonego)

REST API Endpoint: / db / data / batch (target: / cypher)

Używając indeksu schematu, ograniczenia, MERGE, CREATE UNIQUE.

2. Mój schemat:

neo4j-sh (0)$ schema
==> Indexes
==>   ON :REPLY(created_at)   ONLINE                             
==>   ON :REPLY(ids)          ONLINE (for uniqueness constraint) 
==>   ON :REPOST(created_at) ONLINE                             
==>   ON :REPOST(ids)        ONLINE (for uniqueness constraint) 
==>   ON :Post(userId)      ONLINE                             
==>   ON :Post(postId)    ONLINE (for uniqueness constraint) 
==> 
==> Constraints
==>   ON (post:Post) ASSERT post.postId IS UNIQUE
==>   ON (repost:REPOST) ASSERT repost.ids IS UNIQUE
==>   ON (reply:REPLY) ASSERT reply.ids IS UNIQUE

3. Moje szyfrowane zapytania i żądania JSON

3.1. Gdy jeden rekord wymaga utworzenia pojedynczego węzła, opis zadania wygląda jak poniżej

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (child:Post {postId:1001, userId:901})"}}

3.2. Gdy jeden rekord wymaga dwóch węzłów z jedną relacją do utworzenia, opis zadania wygląda jak poniżej

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (parent:Post {postId:1002, userId:902}) MERGE (child:Post {postId:1003, userId:903}) CREATE UNIQUE parent-[relationship:REPOST {ids:'1002_1003', created_at:'Wed Nov 06 14:06:56 AST 2013' }]->child"}}

3.3. Zwykle wysyłam 100 opisów zadań (mieszanych 3.1 i 3.2) na partię, co zajmuje około 150 ~ 250ms, aby to zrobić.

4. Problemy z wydajnością

4.1. Konkurencja:

/ db / data / batch (target: / cypher) wydaje się nie być bezpieczny dla wątków, testowany z dwoma lub więcej współbieżnymi wątkami, które sprowadziły serwer Neo4j w ciągu sekund (s) ~ minut (y).

4.2. MERGE z ograniczeniami nie zawsze działa.

Podczas tworzenia dwóch węzłów i jednej relacji z pojedynczym zapytaniem (wspomnianym powyżej w 3.2.), Czasami działa jak urok; ale czasami zawiedzie z wyjątkiem CypherExecutionException i powiedzenie, że jeden z Node xxxx już istnieje z etykietą aaaa i właściwością „bbbbb” = [ccccc]; Z mojego zrozumienia wynika, że ​​MERGE nie zakłada powrotu żadnego wyjątku, ale zwraca węzeł, jeśli już istnieje.

W wyniku wyjątku cała partia zakończy się niepowodzeniem i wycofaniem, co wpływa na moją szybkość wstawiania.

W tym wydaniu otworzyłem problem w GitHub,https://github.com/neo4j/neo4j/issues/1428

4.3. TWORZENIE UNIKATU z ograniczeniami nie zawsze działa w przypadku tworzenia relacji.

Jest to również wspomniane w tym samym wydaniu github.

4.4. Wydajność:

Właściwie, zanim użyję partii z szyfrowaniem, wypróbowałem starsze indeksowanie za pomocą get_or_create (/ db / data / index / node / Post? Uniqueness = get_or_create & / db / data / index / relationship / XXXXX? Uniqueness = get_or_create)

Ze względu na charakter tych starszych punktów końcowych indeksu (zwracają lokalizację danych w indeksie zamiast lokalizacji danych w rzeczywistym przechowywaniu danych), więc nie mogłem ich użyć w partii (potrzebna była funkcja węzła odsyłającego utworzona wcześniej w tej samej partii) )

Wiem, że mogę włączyć funkcję auto_indexing i zajmować się przechowywaniem danych bezpośrednio zamiast indeksu starszego, ale wspomnieli o wersji 2.0.0, indeks schematu jest zalecany w stosunku do starszego indeksu, więc decyduję się na przejście do metody indeksowania + szyfrowania + schematu.

JEDNAK, w przypadku batch + cypher, mogę uzyskać tylko około 200 opisów zadań na sekundę szybkości wstawiania, byłoby to znacznie wyższe, gdyby MERGE z ograniczeniami zawsze działało, powiedzmy około 600 ~ 800 / s, ale nadal jest znacznie niższe niż 5 kB / s. Wypróbowałem także indeks schematu bez żadnych ograniczeń, ale osiągnięto jeszcze niższą wydajność pod względem szybkości wstawiania.

questionAnswers(1)

yourAnswerToTheQuestion