保存CRUDRepository的方法很慢?
我想在我的neo4j数据库中存储一些数据。 我使用spring-data-neo4j。
我的代码如下:
for (int i = 0; i < newRisks.size(); i++) { myRepository.save(newRisks.get(i)); System.out.println("saved " + newRisks.get(i).name); }
我的newRisks-array包含大约60000个对象和60000个边。 每个节点和边都有一个属性。 这个循环的持续时间大约是15-20分钟,这是正常的吗? 我使用Java VisualVM来搜索一些瓶颈,但我的平均CPU使用率为10 – 25%(4个核心),而我的堆不到一半。
有什么选择来推动这项行动吗?
编辑:附加是,在第一次调用myRepository.save(newRisks.get(i));
在第一个输出到来之前几分钟,jvm下降了fpr
第二次编辑:
类风险:
@NodeEntity public class Risk { //... @Indexed public String name; @RelatedTo(type = "CHILD", direction = Direction.OUTGOING) Set risk = new HashSet(); public void addChild(Risk child) { risk.add(child); } //... }
创造风险:
@Autowired private Repository myRepository; @Transactional public Collection makeSomeRisks() { ArrayList newRisks = new ArrayList(); 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; }
这里的问题是你正在使用不适用于此的API进行批量插入。
你创建一个风险和60k的孩子,你首先保存根,同时也保持60k儿童(并创建关系)。 这就是为什么第一次保存需要这么长时间。 然后你再次拯救孩子们。
有一些解决方案可以加快SDN的速度。
-
不要使用集合方法进行大量插入,保持两个参与者并使用template.createRelationshipBetween(root,child,“CHILD”,false);
-
首先坚持孩子,然后将所有持久的孩子添加到根对象并坚持下去
-
正如您所做的那样,使用Neo4j-Core API但调用template.postEntityCreation(node,Risk.class),以便您可以通过SDN访问实体。 然后你还必须自己索引实体(db.index.forNodes(“Risk”)。add(node,“name”,name);)(或者使用neo4j core-api auto-index,但那不是与SDN兼容)。
-
无论使用core-api还是SDN,您都应该使用大约10-20k节点/ rels的tx大小以获得最佳性能
我想我找到了一个解决方案:
我使用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(); }
结果:在几秒之后,数据库充满了风险。
也许reflection会使用spring-data-neo4j减慢这个程序。 @Michael Hunger在他的书GoodRelationships中说了这样的话,谢谢你的提示。
插入到您的数据库(Java之外)是否具有相同的延迟,或者仅通过弹簧数据这是一个问题?
我遇到了与OP相同的问题。 在我的情况下真的很有用的是将Neo4j的使用从远程服务器模式改为嵌入式 。 可以在此处找到嵌入式SDN使用的良好示例。