hil*_*ert 5 java jvm neo4j database-performance spring-data-neo4j
我想在我的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);
}
Run Code Online (Sandbox Code Playgroud)
我的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);
}
//...
}
Run Code Online (Sandbox Code Playgroud)
创造风险:
@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;
}
Run Code Online (Sandbox Code Playgroud)
我想我找到了一个解决方案:
我尝试使用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();
}
Run Code Online (Sandbox Code Playgroud)
结果:在几秒之后,数据库充满了风险.
也许反射会使用spring-data-neo4j减慢这个程序.@Michael Hunger在他的书GoodRelationships中说了这样的话,谢谢你的提示.
这里的问题是你正在使用不适用于此的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大小以获得最佳性能