4

10000 個のバッチで 100 万個の Neo4j ノードを作成し、各バッチは独自のトランザクションで作成しました。奇妙なことに、このプロセスをマルチスレッド実行で並列化しても、パフォーマンスにプラスの効果はありませんでした。異なるスレッドのトランザクションが互いにブロックしているようです。

これは、並列コレクションを使用してこれをテストする Scala コードの一部です。

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

build.sbtビルドと実行に必要な行は次のとおりです。

scalaVersion := "2.9.2"

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

fork in run := true

.par外部の呼び出しの前に呼び出しを削除および追加することにより、並列モードと順次モードを切り替えることができますforeach.parコンソール出力は、実行が実際にマルチスレッドであることを明確に示しています。

このコードの同時実行性で起こりうる問題を除外するために、アクターベースの実装も試しましたが、ほぼ同じ結果が得られました (順次バージョンと並列バージョンでそれぞれ 6 秒と 7 秒)。

問題は、私が何か間違ったことをしたのか、それとも Neo4j の制限なのかということです。ありがとう!

4

2 に答える 2

4

主な問題は、あなたの tx がほぼ同時に到着することです。また、トランザクションのコミットは、トランザクション ログへのシリアル化された書き込みです。書き込みが時間的にインターリーブされ、実際のノード作成がより高価なプロセスになると、スピードアップが得られます。

于 2012-09-27T22:58:36.320 に答える
2

バッチ挿入は、複数のスレッドでは機能しません。neo4j ドキュメントから:

常に 1 つのスレッドでバッチ挿入を実行し (または同期を使用して、一度に 1 つのスレッドのみがバッチ インサーターにアクセスするようにします)、終了したらシャットダウンを呼び出します。

Neo4j バッチ挿入

于 2012-09-27T09:41:39.340 に答える