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加快速度。

  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自动索引,但这不是与SDN兼容)。

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