2012-09-25 8 views
4

J'ai créé 1 million de nœuds Neo4j par lots de 10000, chaque batch dans sa propre transaction. Ce qui est étrange, c'est que paralléliser ce processus avec une exécution multithread n'a eu aucun effet positif sur les performances. C'est comme si les transactions de différents threads se bloquaient les unes les autres.Création de nœuds multithread dans Neo4j

Voici un morceau de code Scala qui teste avec l'aide des collections parallèles:

import org.neo4j.kernel.EmbeddedGraphDatabase 

object Main extends App { 

    val total = 1000000 
    val batchSize = 10000 

    val db = new EmbeddedGraphDatabase("neo4yay") 

    Runtime.getRuntime().addShutdownHook(
     new Thread(){override def run() = db.shutdown()} 
    ) 

    (1 to total).grouped(batchSize).toSeq.par.foreach(batch => { 

     println("thread %s, nodes from %d to %d" 
      .format(Thread.currentThread().getId, batch.head, batch.last)) 

     val transaction = db.beginTx() 
     try{ 
      batch.foreach(db.createNode().setProperty("Number", _)) 
     }finally{ 
      transaction.finish() 
     } 
    }) 
} 

et voici les build.sbt lignes nécessaires pour la construction et l'exécuter:

scalaVersion := "2.9.2" 

libraryDependencies += "org.neo4j" % "neo4j-kernel" % "1.8.M07" 

fork in run := true 

On peut basculer entre les modes parallèle et séquentiel en supprimant et en ajoutant .par appel avant le foreach externe. La sortie de la console montre clairement que l'exécution .par est en effet multithread. Pour exclure d'éventuels problèmes de concurrence dans ce code, j'ai également essayé une implémentation basée sur l'acteur, avec à peu près le même résultat (6 et 7 secondes pour les versions séquentielles et parallèles, respectivement). Donc, la question est: ai-je fait quelque chose de mal ou est-ce une limitation de Neo4j? Merci!

Répondre

4

Le principal problème est que vos tx arrivent à peu près en même temps. Et les validations de transaction sont sérialisées dans le journal des transactions. Si les écritures sont entrelacées dans le temps et que la création du nœud est plus coûteuse, vous obtiendrez une accélération.

2

L'insertion par lots ne fonctionne pas avec plusieurs threads. De la documentation Neo4j:

Toujours effectuer l'insertion par lots dans un seul fil (ou utiliser la synchronisation pour faire un seul fil à un accès en temps le dispositif d'insertion par lots) et invoquer l'arrêt une fois terminé.

Neo4j Batch insert

+2

L'outil d'insertion par lots n'est pas ce qu'Oleg a utilisé mais l'API transactionnelle normale :) –

+0

Je suppose que je lis beaucoup de "batch" es dans le texte ;-) Mais écrire avec plusieurs threads dans un fichier sera goulot par la vitesse io (comme vous avez répondu). – Jan

Questions connexes