2012-03-05 8 views
5

Voglio memorizzare alcuni dati nel mio database neo4j. Io uso spring-data-neo4j per quello.di CRUDRepository è molto lento?

il mio codice è come il seguente:

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

mio newRisks-array contiene circa 60000 oggetti e 60000 bordi. Ogni nodo e spigolo ha una proprietà. La durata di questo ciclo è di circa 15 - 20 minuti, è normale? Ho usato Java VisualVM per cercare alcuni colli di bottiglia, ma il mio utilizzo medio della CPU era del 10 - 25% (di 4 core) e il mio heap era meno della metà pieno.

Ci sono delle opzioni per potenziare questa operazione?


EDIT: supplementare è, per la prima chiamata di myRepository.save(newRisks.get(i)); JVM caduta assleep fpr alcuni minuti prima della prima uscita è venuta

Secondo EDIT:

Classe rischio:

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

    //... 
} 

Creazione di rischi:

@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

In base alla [documentazione] (http://static.springsource.org/spring-data/data-neo4j/docs/2.0.0.RC1/api/org/springframework/data/neo4j/repository/CRUDRepository. html), CRUDRepository.save può prendere un Iterable come argomento. Perché non solo myRepository.save (newRisks)? – Thomas

+0

ho provato questo e funziona anche. ma non è più veloce. così posso vedere, non è morto ^^ – hilbert

+0

potresti mostrare la struttura della tua classe e qualsiasi entità di nodo e entità di relazione a cui si riferisce. E il metodo di costruzione delle istanze di rischio? –

risposta

5

Il problema qui è che si stanno facendo inserimenti di massa con un'API non prevista per questo.

Si crea un rischio e 60k bambini, si salva prima la radice che persiste anche i 60k bambini allo stesso tempo (e crea le relazioni). Ecco perché il primo salvataggio richiede così tanto tempo. E poi salvi di nuovo i bambini.

Esistono alcune soluzioni per velocizzarlo con SDN.

  1. non utilizzare il metodo di raccolta per gli inserti di massa, persistono entrambi i partecipanti e l'uso template.createRelationshipBetween (radice, bambino, "bambino", false);

  2. persistono i bambini prima quindi aggiungere tutti i bambini persistenti per l'oggetto principale e persistono che

  3. Come avete fatto, utilizzare l'API Neo4j-Core, ma chiamano template.postEntityCreation (nodo, Risk.class) così che puoi accedere alle entità tramite SDN.Quindi devi anche indicizzare le entità da te (db.index.forNodes ("Rischio"). Aggiungi (nodo, "nome", nome);) (oppure usa l'auto-index neo4j core-api, ma non è così compatibile con SDN).

  4. Indipendentemente con il core-API o SDN si dovrebbe usare TX-dimensioni di circa 10-20k nodi/REL per le migliori prestazioni

+0

grazie hai ragione. Per il primo ho appena salvato la radice, ci vogliono solo 6 minuti. Forse più tardi devo provare le altre soluzioni che proponi. – hilbert

1

Gli inserimenti nel database (al di fuori di Java) hanno lo stesso ritardo o si tratta di un problema solo tramite dati primaverili?

+0

buona idea, ma come posso inserire questo conteggio di note ecc da java? non voglio prendere un altro linguaggio di programmazione. Un'altra idea: posso provare a usare lo standard neo4j java api, non spring-data-neo4j. – hilbert

+0

È sufficiente attivare un'istruzione di inserimento nell'editor di scelta SQL. Questo testerebbe la velocità del database stesso, al di fuori di qualsiasi linguaggio di programmazione. – abehrens

+0

è un database noSQL, ma ho provato con natic java api per neo4j, che è più veloce – hilbert

5

Credo di aver trovato una soluzione:

ho provato lo stesso inserto utilizzando il Nativ Neo4j API Java:

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

il risultato: dopo qualche sconds, il database è piena di rischi .

Forse i riflessi rallentano questa routine con spring-data-neo4j. @Michael Hunger dice qualcosa del genere nel suo libro GoodRelationships, grazie per il suggerimento.

+0

questo mi ha salvato la giornata! molto apprezzato, grazie. – jarandaf

1

Ho affrontato lo stesso problema di OP. Davvero utile nel mio caso è stato quello di modificare l'utilizzo di Neo4j dalla modalità server remoto a a incorporata. Un buon esempio di utilizzo di SDN incorporato potrebbe essere trovato here.