2012-03-05 12 views
5

quiero almacenar algunos datos en mi base de datos neo4j. uso spring-data-neo4j para eso.método de guardar de CRUDRepository es muy lento?

mi código es como el siguiente:

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

Mi newRisks-matriz contiene alrededor de 60000 y 60000 objetos de bordes. Cada nodo y borde tiene una propiedad. La duración de este ciclo es de 15 a 20 minutos, ¿es esto normal? Utilicé Java VisualVM para buscar algunos cuellos de botella, pero el uso promedio de mi CPU fue del 10 al 25% (de 4 núcleos) y mi pila estaba menos de la mitad.

¿Hay alguna opción para impulsar esta operación?


EDIT: adicional es, en la primera llamada de myRepository.save(newRisks.get(i)); la JVM caer assleep FPR algunos minutos antes de la primera salida está llegando

Segunda EDIT:

Clase de riesgo:

@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); 
    } 

    //... 
} 

Creación de riesgos:

@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

Según la [documentación] (http://static.springsource.org/spring-data/data-neo4j/docs/2.0.0.RC1/api/org/springframework/data/neo4j/repository/CRUDRepository. html), CRUDRepository.save puede tomar un Iterable como argumento. ¿Por qué no solo myRepository.save (newRisks)? – Thomas

+0

intenté esto y funciona también. pero, no es más rápido. entonces puedo ver, él no está muerto ^^ – hilbert

+0

podría mostrar la estructura de su clase y cualquier nodo-entidades y relaciones-entidades a las que se refiere. ¿Y el método de construcción de sus instancias de riesgo? –

Respuesta

5

El problema aquí es que estás haciendo inserciones masivas con una API que no está pensada para eso.

Crea un riesgo y 60k hijos, primero guarda la raíz que también persiste a los 60,000 hijos al mismo tiempo (y crea las relaciones). Es por eso que el primer rescate lleva tanto tiempo. Y luego guardas a los niños otra vez.

Existen algunas soluciones para acelerarlo con SDN.

  1. no utilice el método de recopilación para las inserciones masivas, persisten los dos participantes y utilizar template.createRelationshipBetween (raíz, niño, "niño", false);

  2. persisten los niños primero y luego se suman todos los niños persistió al objeto raíz y persisten que

  3. Al igual que hizo, utilice la API Neo4j-Core, pero llaman template.postEntityCreation (nodo, Risk.class) por lo que puede acceder a las entidades a través de SDN.Luego también debe indexar las entidades por su cuenta (db.index.forNodes ("Risk"), add (node, "name", name);) (o use el auto-index neo4j core-api, pero eso no es así) compatible con SDN).

  4. Independientemente con el núcleo-API o SDN se debe utilizar tx-tamaños de alrededor de 10-20k nodos/REL para un mejor rendimiento

+0

gracias, tienes razón. Para la primera vez que guardo la raíz, toma solo 6 minutos. Quizás más tarde tenga que probar las otras soluciones que propones. – hilbert

1

¿Las inserciones en su base de datos (fuera de Java) tienen la misma demora o solo es un problema a través de los datos de primavera?

+0

buena idea, pero ¿cómo puedo insertar este conteo de notas, etc. de Java? No quiero tomar otro lenguaje de programación. Otra idea: puedo intentar usar el estándar neo4j java api, no spring-data-neo4j. – hilbert

+0

Simplemente ejecute una instrucción de inserción en su editor de SQL de su elección. Esto probaría la velocidad de la base de datos, fuera de cualquier lenguaje de programación. – abehrens

+0

es una base de datos no SQL, pero lo he intentado con la aplicación nati java para neo4j, eso es más rápido – hilbert

5

creo que he encontrado una solución:

Probé la misma inserción utilizando la API Java Nativ Neo4j:

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(); 
} 

el resultado: después de algunos sconds, la base de datos está llena de riesgos .

Tal vez los reflejos ralentizan esta rutina con spring-data-neo4j. @Michael Hunger dice algo así en su libro GoodRelationships, gracias por ese consejo.

+0

¡esto me salvó el día! muy apreciado, gracias. – jarandaf

1

me enfrenté al mismo problema que la OP. Realmente útil en mi caso fue cambiar el uso de Neo4j del modo del servidor remoto al incrustado. Se puede encontrar un buen ejemplo de uso de SDN incorporado here.