1

私は現在、大量のノード/関係をグラフに挿入するという観点から、neo4j を評価しています。バッチ挿入で達成できる最初の挿入についてではありません。組み込みモードでneo4jを使用するJavaアプリケーション(spring-data-neo4j 2.2.2.RELEASEに同梱されているため、現在バージョン1.8.1)で実行時に頻繁に処理される挿入についてです。

これらの挿入は通常、スター スキーマに従うノードです。1 つのノード (インポートされたデータセットのルート ノード) には、最大1000000 (100 万!)の接続された子ノードがあります。子ノードは通常、他の追加ノードとも関係があります。しかし、これらの関係は、これまでのところこのテストではカバーされていません。全体的な目標は、その量のデータを最大 5 分でインポートすることです。

Neo4jTemplateこのような種類の挿入をシミュレートするために、ノードと関係を作成するために を使用する小さな junit テストを作成しました。挿入された各リーフには、後で処理するために関連付けられたキーがあります。

@Test
@Transactional
@Rollback
public void generateUngroupedNode()
        {
        long numberOfLeafs = 1000000;
        Assert.assertTrue(this.template.transactionIsRunning());
        Node root = this.template.createNode(map(NAME, UNGROUPED));
        String groupingKey = null;
        for (long index = 0; index < numberOfLeafs; index++)
            {
            // Just a sample division of leafs to possible groups
            // Creates keys to be grouped by to groups containing 2 leafs each
            if (index % 2 == 0)
                {
                groupingKey = UUID.randomUUID().toString();
                }
            Node leaf = this.template.createNode(map(GROUPING_KEY, groupingKey, NAME, LEAF));
            this.template.createRelationshipBetween(root, leaf, Relationships.LEAF.name(),
                    map());
            }
        }

このテストでは、gcrガベージ コレクターの問題を回避するためにキャッシュを使用します。

cache_type=gcr
node_cache_array_fraction=7
relationship_cache_array_fraction=5
node_cache_size=400M
relationship_cache_size=200M

さらに、私は次のように設定MAVEN_OPTSしました:

export MAVEN_OPTS="-Xmx4096m -Xms2046m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit"

とにかく、そのテストを実行すると、常にJava heap spaceエラーが発生します。

java.lang.OutOfMemoryError: Java heap space
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
    at java.lang.Class.getMethod0(Class.java:2670)
    at java.lang.Class.getMethod(Class.java:1603)
    at org.apache.commons.logging.LogFactory.directGetContextClassLoader(LogFactory.java:896)
    at org.apache.commons.logging.LogFactory$1.run(LogFactory.java:862)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.apache.commons.logging.LogFactory.getContextClassLoaderInternal(LogFactory.java:859)
    at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:423)
    at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
    at org.springframework.transaction.support.TransactionTemplate.<init>(TransactionTemplate.java:67)
    at org.springframework.data.neo4j.support.Neo4jTemplate.exec(Neo4jTemplate.java:403)
    at org.springframework.data.neo4j.support.Neo4jTemplate.createRelationshipBetween(Neo4jTemplate.java:367)

より少ない量のデータでいくつかのテストを行った結果、次の結果が得られました。1 つのノードが接続されています:

  • 50000 リーフ: 3035ms
  • 100000 リーフ: 4290ms
  • 200000 リーフ: 10268ms
  • 400000 リーフ: 20913ms
  • 800000 リーフ: Java ヒープ領域

これらの操作中のシステム モニターのスクリーンショットを次に示します。

システムモニター

正確に何が実行され、ヒープに保存されているかについてより良い印象を得るために、最後のテスト (800000 リーフ) で JProfiler を実行しました。ここにいくつかのスクリーンショットがあります:

ヒープ使用量:

ヒープ

CPU使用率:

CPU

私にとっての大きな疑問は、neo4j はそのような膨大な量のデータを使用するように設計されていないのでしょうか? または、そのような種類の挿入 (およびその後の操作) を実現する他の方法はありますか? 公式の neo4j Web サイトとさまざまなスクリーンキャストで、neo4j が数十億のノードと関係で実行できるという情報を見つけました (例: http://docs.neo4j.org/chunked/stable/capabilities-capacity.html )。JPAなどでヒープを手動でクリーンに保つために利用できるような機能flush()やメソッドは見つかりませんでした。clean()

その量のデータでneo4jを使用できるのは素晴らしいことです. すでに 200000 枚のリーフがグラフに保存されているため、組み込みの従来の RDBMS と比較して、パフォーマンスが 10 倍以上向上していることに気付きました。私は、neo4j が提供するようなデータ モデリングとそれらのデータのクエリの優れた方法をあきらめたくありません。

4

2 に答える 2