我想在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> 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 :(得分: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();
}
结果: 在几秒之后,数据库充满了风险。
也许反射会使用spring-data-neo4j减慢这个例程。 @Michael Hunger在他的书GoodRelationships中说了这样的话,谢谢你的提示。
答案 1 :(得分:5)
这里的问题是你正在使用不适用于此的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节点/相关的tx大小以获得最佳性能
答案 2 :(得分:1)
您的数据库(Java之外)的插入是否具有相同的延迟,或者只是通过弹簧数据这是一个问题?
答案 3 :(得分:1)
I faced the same problem as OP. Really useful in my case was to change Neo4j usage from remote server mode to embedded. Good example of embedded SDN usage could be found here.