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数组包含大约60000个对象和60000个边。每个节点和边缘都有一个属性。此循环的持续时间大约为15-20分钟,这正常吗?我使用Java
VisualVM搜索一些瓶颈,但是我的平均CPU使用率为10%-25%(4个内核),堆的容量不足一半。
有什么选择可以增强此操作?
编辑: 额外的是,在第一次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;
}
问题答案:
这里的问题是您正在使用不适合该用途的API进行大量插入。
创建一个Risk和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自动索引,但这不是与SDN兼容)。
-
无论使用core-api还是SDN,都应使用大约10-20k节点/ rel的tx大小以获得最佳性能。