保存CRUDRepository的方法很慢?

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)

hil*_*ert 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();
}
Run Code Online (Sandbox Code Playgroud)

结果:在几秒之后,数据库充满了风险.

也许反射会使用spring-data-neo4j减慢这个程序.@Michael Hunger在他的书GoodRelationships中说了这样的话,谢谢你的提示.


Mic*_*ger 5

这里的问题是你正在使用不适用于此的API进行批量插入.

你创建一个风险和60k的孩子,你首先保存根,同时也保持60k儿童(并创建关系).这就是为什么第一次保存需要这么长时间.然后你再次拯救孩子们.

有一些解决方案可以加快SDN的速度.

  1. 不要使用集合方法进行大量插入,坚持参与者并使用template.createRelationshipBetween(root,child,"CHILD",false);

  2. 首先坚持孩子,然后将所有持久的孩子添加到根对象并坚持下去

  3. 正如您所做的那样,使用Neo4j-Core API但调用template.postEntityCreation(node,Risk.class),以便您可以通过SDN访问实体.然后你还必须自己索引实体(db.index.forNodes("Risk").add(node,"name",name);)(或者使用neo4j core-api auto-index,但那不是与SDN兼容).

  4. 无论使用core-api还是SDN,您都应该使用大约10-20k节点/ rels的tx大小以获得最佳性能