2012-03-05 38 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找到。