Optimización de inserciones por lotes de alto volumen en Neo4j usando REST

Necesito insertar una gran cantidad de nodos con relaciones entre ellos en Neo4j a través del punto final de Lote de REST API, aproximadamente 5k registros / s (aún en aumento).

Esta será la inserción continua 24x7. Cada registro puede requerir la creación de un solo nodo, pero otro puede requerir dos nodos y una relación que se está creando.

¿Puedo mejorar el rendimiento de las inserciones cambiando mi procedimiento o modificando la configuración de Neo4j?

Mi progreso hasta ahora:

1. He estado probando con Neo4j por un tiempo, pero no pude obtener el rendimiento que necesitaba

Cuadro de servidor de prueba: 24 cores + 32GB RAM

Neo4j 2.0.0-M06 instalado como un servicio independiente.

Ejecutar mi aplicación Java en el mismo servidor. (Las aplicaciones Neo4j y Java deberán ejecutarse en su propio servidor en el futuro, por lo que no se puede usar el modo integrado)

Punto final de la API REST: / db / data / batch (target: / cypher)

Usando el índice de esquema, restricciones, MERGE, CREATE UNIQUE.

2. Mi esquema:

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. Mis consultas en clave y solicitudes JSON

3.1. Cuando un registro requiere la creación de un solo nodo, la descripción del trabajo se ve a continuación

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

3.2. Cuando un registro requiere dos nodos con una relación para crearse, la descripción del trabajo se ve a continuación.

{"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. Por lo general, envío 100 descripciones de trabajo (3.1 y 3.2 mixtas) por lote, lo cual toma alrededor de 150 ~ 250 ms para completarlo.

4. Problemas de rendimiento.

4.1. Concurrencia

/ db / data / batch (target: / cypher) parece no ser seguro para subprocesos, probado con dos o más subprocesos concurrentes que hicieron que el servidor Neo4j cayera dentro de los segundos (s) ~ minutos (s).

4.2. MERGE con restricciones no siempre funciona.

Al crear dos nodos y una relación con una sola consulta (mencionada anteriormente en 3.2.), A veces funciona como un encanto; pero en algún momento falla con una CypherExecutionException y dice que uno de los Nodos xxxx ya existe con la etiqueta aaaa y la propiedad "bbbbb" = [ccccc]; a mi entender, el MERGE no supone devolver ninguna excepción, sino devolver el nodo si ya existe.

Como resultado de la excepción, todo el lote fallará y retrocederá, lo que afectará mi tasa de inserción.

He abierto un problema en GitHub para este problema,https://github.com/neo4j/neo4j/issues/1428

4.3. CREAR ÚNICO con restricciones no siempre funciona para la creación de relaciones.

Esto también se menciona en el mismo tema de github.

4.4. Actuación:

En realidad, antes de usar batch con cypher, he probado la indexación heredada con get_or_create (/ db / data / index / node / Post? Uniqueness = get_or_create & / db / data / index / relationship / XXXXX? Uniqueness = get_or_create)

Debido a la naturaleza de los puntos finales heredados del índice (devuelven la ubicación de los datos en el índice en lugar de la ubicación de los datos en el almacenamiento de datos real), por lo que no pude usarlos dentro de un lote (se necesita la función del nodo de referencia creado anteriormente en el mismo lote) )

Sé que podría habilitar el autoindexado y lidiar con el almacenamiento de datos directamente en lugar del índice heredado, pero mencionaron desde 2.0.0, el índice de esquema se recomienda sobre el índice heredado, por lo que decido cambiar al enfoque de índice por lotes + cifrado + esquema.

SIN EMBARGO, con batch + cypher, solo puedo obtener aproximadamente 200 descripciones de trabajos por segundo de inserción, habría sido mucho más alto si el MERGE con restricciones siempre funcionara, digamos unos 600 ~ 800 / s, pero aún así es mucho menor que 5k / s También probé el índice de esquema sin ningún tipo de restricción, terminó con un rendimiento aún menor en términos de tasa de inserción.

Respuestas a la pregunta(1)

Su respuesta a la pregunta