2012-03-05 67 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個邊緣。每個節點和邊都有一個屬性。 這個循環的持續時間大約是15-20分鐘,這是正常的嗎? 我使用Java VisualVM來搜索一些瓶頸,但是我的平均CPU使用率是4 - 核心的10 - 25%,我的堆少於一半。

有什麼辦法可以加強這個操作?


編輯:額外的,對myRepository.save(newRisks.get(i));第一次調用JVM的下降assleep FPR第一輸出前幾分鐘被正在添加

第二個編輯:

類風險:

@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

根據[文檔](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 2012-03-05 14:51:16

+0

我試過了,它也有效。但是,它不會更快。所以我可以看到,他沒有死^^ – hilbert 2012-03-05 14:54:57

+0

你能否展示你的類的結構以及它引用的任何節點實體和關係實體。你的Risk實例的構造方法是什麼? – 2012-03-06 07:48:05

回答

5

這裏的問題是,你正在做一個API的大規模插入不是爲了那個。

您創建一個風險和60k的孩子,你首先保存同時堅持60k孩子的根(並創建關係)。這就是爲什麼第一次保存需要這麼長時間。然後你再次拯救孩子。

有一些解決方案可以加速SDN。

  1. 不使用大規模嵌入式徵收方式,堅持兩個參與者,並使用template.createRelationshipBetween(根,孩子,「孩子」,假);

  2. 堅持孩子第一,那麼所有的持久孩子添加到根對象,並堅持認爲

  3. 像你一樣,使用Neo4j的核心API但撥打template.postEntityCreation(節點,Risk.class)等等您可以通過SDN訪問實體。然後你也必須自己編寫實體(db.index.forNodes(「Risk」).add(node,「name」,name);)(或者使用neo4j core-api auto-index,但這不是與SDN兼容)。無論與核心API或SDN你應該使用周圍10-20K節點/ RELS的TX-尺寸爲最佳性能

+0

謝謝你是對的。首先我只保存根,只需要6分鐘。也許以後我必須嘗試你提出的其他解決方案。 – hilbert 2012-03-12 07:55:29

1

插入數據庫(Java外部)的延遲是否相同?或者只是通過彈簧數據造成這個問題?

+0

好主意中添加了「第二編輯:」下的信息,但是我怎樣才能從java中插入這樣的筆記數呢?我不想採取其他編程語言。另一個想法:我可以嘗試使用標準的neo4j java api,而不是spring-data-neo4j。 – hilbert 2012-03-06 07:05:31

+0

只需在您選擇的SQL編輯器中觸發一條插入語句。這將在任何編程語言之外測試數據庫本身的速度。 – abehrens 2012-03-07 17:28:37

+0

它是一個noSQL數據庫,但我已經嘗試了與neo4j的natic java api,那更快的 – hilbert 2012-03-08 08:44:09

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 2013-04-07 20:27:18

1

  • 我面臨同樣的問題,因爲OP。在我的情況下真正有用的是將Neo4j的使用從遠程服務器模式更改爲嵌入式。嵌入式SDN使用的好例子可以在here找到。