gpt4 book ai didi

c# - 在单个事务中将 2M 节点/关系插入 Neo4J 永远不会成功

转载 作者:行者123 更新时间:2023-11-30 17:31:15 26 4
gpt4 key购买 nike

我最近一直在使用 neo4j/cypher 来将对象存储到其中。我将 netcore 与 neo4j.Driver v1.5 一起使用。

一切都很好,直到我需要更高的性能,因为我将需要在运行时存储数百万个节点/关系。

在花了一些时间研究其他一些问题和文章之后,我决定重构我在以“天真”方式调用 neo4j 时所拥有的东西。 (每次创建 1 个请求)

我现在通过以下方式使用查询参数来减少查询次数:

用于节点创建

MERGE (model:EngineeringModel {id: $engineeringModelId})
WITH model
UNWIND $nodes AS node
CREATE (thing:Label1:Label2:LabelN)<-[:Model]-(model)
SET thing = node

其中 $engineeringModelId 是一个字符串,$nodes 是一个对象数组,对应于每个节点的属性。

为了建立关系

MATCH (model:EngineeringModel {id: $engineeringModelId}) USING INDEX 
model:EngineeringModel(id)
UNWIND $relationships AS relationship
MATCH (s:Label1 {id: relationship.source}) USING INDEX s:Label1(id)
UNWIND relationship.sourceRelationships AS sourceRelationship
UNWIND sourceRelationship.targets AS target
MATCH (t:IIdentifiable {id: target}) USING INDEX t:IIdentifiable(id)
CALL apoc.create.relationship(s, sourceRelationship.type, {{}}, t) YIELD rel
RETURN rel

在哪里,$engineeringModelId 是一个字符串,$relationships 是包含源节点及其所有目标/关系类型的对象数组。

我设法在 5 分钟内使用事务函数保存了大约 100 万个节点/关系,并将请求拆分为多达 20000 个对象。 (拆分在C#代码中完成)

using (var session = Driver.Session())
{
session.WriteTransaction(tx => tx.Run(request, params));
}

问题在于,在每 20000 个节点/关系执行一次提交的意义上,它不是“事务安全”的。

使用 4.3.2.3 中描述的显式事务 neo4j docs我无法在合理的时间内执行提交(我从未设法保存)。

this.driverLifeCycle.BeginTransaction(); // connect and start a new transaction
this.DriverLifeCycle.Transaction.Run(cqlQuery.ToString(), parameters); xN times
this.driverLifeCycle.CommitTransaction(); // commit the transaction

这是我的 docker 容器的配置:

NEO4J_dbms_memory_pagecache_size=2G 
NEO4J_dbms_memory_heap_maxSize=2G
NEO4J_dbms_memory_heap_initial__size=2G

谁知道如何使这个显式事务正常工作?

非常感谢大家的阅读!

最佳答案

因此,经过一些调查以及来自 neo4j-slack 上的 neo4j 社区的一些输入,似乎无法在我的 neo4j (v 3.2.5) 版本中使用驱动程序 v1.5 for .需要 netcore 和“手动”处理事务的解决方法。

解决方法基本上如下:

  • 为所有节点添加一个额外的 TMP 标签,以在当前交易中创建具有根据 POST 请求生成的 transactionId 属性,
  • 在交易期间使用相同交易 ID 创建的关系上添加额外属性 transactionId

我还提交了每几千个(在我的例子中是 10k)个节点/关系,以便 neo4j 可以处理它并确保包含这些额外的标签和属性。

在操作结束时:

  • 成功后,我删除了应用于节点和关系的额外标签和属性

    MATCH (tmpNode:TMP { transactionId: $transactionId })
    USING INDEX tmpNode:TMP(transactionId)
    REMOVE tmpNode:TMP
    REMOVE tmpNode.transactionId

    MATCH ()-[r { transactionId: $transactionId }]->()
    REMOVE r.transactionId
  • 如果出现问题,我会删除所有已创建的节点和关系。

    MATCH (tmpNode:TMP { transactionId: $transactionId })
    USING INDEX tmpNode:TMP(transactionId)
    DETACH DELETE tmpNode

    MATCH ()-[tmpRel { transactionId: $transactionId }]->()
    DELETE tmpRel

这两个操作本可以简化为一个请求而不是 2 个,但考虑到数据量,这样做效率更高。

在我的本地机器上,我设法在大约 10 分钟内运行它,这仍然不是很好,但至少是可行的。

关于c# - 在单个事务中将 2M 节点/关系插入 Neo4J 永远不会成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48212354/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com