2012-03-05 6 views
5

私のneo4jデータベースにいくつかのデータを保存したい。私はspring-data-neo4jを使っています。CRUDRepositoryの保存方法は非常に遅いですか?

私のコードは次のようなものです:

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

マイnewRisksアレイは60000個のオブジェクトと60000のエッジ年頃含まれています。すべてのノードとエッジには1つのプロパティがあります。 このループの持続時間は約15〜20分ですが、これは正常ですか? Java VisualVMを使用していくつかのボトルネックを検索しましたが、私の平均CPU使用率は10%〜25%(4コア)でした。ヒープが半分以下でした。

この操作を強化するオプションはありますか?


EDIT:追加され、myRepository.save(newRisks.get(i));の最初の呼び出しに最初の出力の前にいくつかの分FPR JVM落下assleepが来ている

第二EDIT:

クラスリスク:

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

    //... 
} 

リスクを作成する:

@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

[documentation](http://static.springsource.org/spring-data/data-neo4j/docs/2.0.0.RC1/api/org/springframework/data/neo4j/repository/CRUDRepository)によると、 html)、CRUDRepository.saveは引数としてIterableをとることができます。なぜmyRepository.save(newRisks)だけではないのですか? – Thomas

+0

私はこれを試して、それも動作します。しかし、その高速ではありません。だから私は見ることができます、彼は死んでいません^^ – hilbert

+0

あなたのクラスの構造とそれが参照するノードエンティティと関係エンティティを表示できますか?リスクインスタンスの作成方法は? –

答えて

5

ここでの問題は、意図していないAPIを使用して大量挿入を行っていることです。

リスクと60kの子供を作成すると、最初に60kの子供を同時に持続するルートを保存します(そして関係を作成します)。だからこそ、最初の保存には時間がかかります。そして、あなたは再び子供たちを救います。

SDNでスピードアップするいくつかのソリューションがあります。

  1. (偽ルート、子、「CHILD」)の両方の参加者を持続し、template.createRelationshipBetweenを使用し、大量の挿入のためのコレクションのアプローチを使用しないでください。

  2. は、子どもたちが最初にそのようにルートオブジェクトにすべての永続子を追加し、持続

  3. ことをあなたが行ったように、のNeo4jコアAPIを使用しますが(ノード、Risk.class)template.postEntityCreationを呼び出す持続しますあなたはSDN経由でエンティティにアクセスできます。また、エンティティを独自にインデックスする必要もあります(db.index.forNodes( "Risk")。add(node、 "name"、name);)(またはneo4j core-api auto-indexを使用します。 SDNと互換性があります)。

  4. かかわらず、あなたは最高のパフォーマンスを得るために周り10-20kノード/当該relsのTX-サイズを使用する必要がありますコアAPIまたはSDN

+0

ありがとうございます。最初に私はちょうどルートを保存し、それはわずか6分かかります。たぶん後であなたが提案する他のソリューションを試してみる必要があります。 – hilbert

1

あなたのデータベース(Java以外のもの)に挿入するのが同じ遅延を持つのですか、これは春のデータだけで問題になるのですか?

+0

の投稿に追加しましたが、どのようにしてこの件数の情報をJavaから挿入できますか?私は他のプログラミング言語を使いたくない。他の考え方:私はspring-data-neo4jではなく、標準のneo4j java apiを使用しようとすることができます。 – hilbert

+0

選択したSQLエディタでinsert文を起動してください。これは、プログラミング言語以外のデータベース自体の速度をテストします。 – abehrens

+0

そのnoSQLデータベースですが、neo4j用のnatic java apiで試してみましたが、これより速く – hilbert

5

私は解決策を見つけたと思う:私はnativののNeo4jのJava APIを使用して同じ挿入を試みた

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

結果:いくつかのsconds後 、データベースはリスクで満たされています。

反射は、spring-data-neo4jでこのルーチンを遅くすることがあります。 @Michael Hungerは、彼の本のGoodRelationshipsのようなものは、そのヒントのおかげで言います。

+0

これは私の一日を保存しました!大変感謝しています。 – jarandaf

1

と私はOPと同じ問題に直面しました。私のケースでは、Neo4jの使用方法をリモートサーバモードからに変更しました。に変更しました。埋め込まれたSDNの使用例の良い例はhereです。

関連する問題