5

我想在我的 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;
}
4

4 回答 4

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中说了类似的话,谢谢你的提示。

于 2012-03-06T15:12:34.313 回答
5

这里的问题是您正在使用不是为此而设计的 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 个节点/rels 的 tx-sizes 以获得最佳性能

于 2012-03-11T22:42:56.403 回答
1

插入数据库(Java 之外)是否有相同的延迟,或者这只是通过 spring 数据的问题?

于 2012-03-05T15:46:44.127 回答
1

我面临与OP相同的问题。对我来说真正有用的是将 Neo4j 的使用从远程服务器模式更改为嵌入式。可以在此处找到嵌入式 SDN 使用的良好示例。

于 2016-04-07T10:45:00.843 回答