如何正确使用 apoc.periodic.iterate 来减少大事务的堆使用?
How to properly use apoc.periodic.iterate to reduce heap usage for large transactions?
我正在尝试使用 apoc.periodic.iterate 在 Neo4j 数据库中执行非常大的事务时减少堆使用。
我一直在遵循 this presentation. 中给出的建议
但是,我的结果与那些幻灯片中观察到的结果不同。
首先,关于我的设置的一些注意事项:
- 使用 Neo4j Desktop,Graph 版本 4.0.3 Enterprise,带有 APOC 4.0.0.10
- 我正在使用 .NET Neo4j 驱动程序 4.0.1 版调用查询。
- neo4j.conf 值:
- dbms.memory.heap.initial_size=2g
- dbms.memory.heap.max_size=4g
- dbms.memory.pagecache.size=2g
这是我运行宁的密码查询:
CALL apoc.periodic.iterate(
"UNWIND $nodes AS newNodeObj RETURN newNodeObj",
"CREATE(n:MyNode)
SET n = newNodeObj",
{batchSize:2000, iterateList:true, parallel:false, params: { nodes: $nodes_in } }
)
以及C#的行:
var createNodesResCursor = await session.RunAsync(createNodesQueryString, new { nodes_in = nodeData });
其中 createNodesQueryString
是上面的查询,nodeData
是一个 List<Dictionary<string, object>>
,其中每个字典只有三个条目:2 个字符串,1 个长。
当尝试 运行 创建 130 万个节点时,我观察到堆使用量(通过 JConsole)一直上升到 4GB 可用空间,并在 ~2.5g - 4g 之间来回跳动。减小批处理大小没有明显的区别,而提高 heap.max_size 会导致堆使用量猛增到几乎与该值一样多。它也真的很慢,需要 30 多分钟才能创建那 130 万个节点。
有谁知道我可能会对链接的演示文稿做什么 wrong/differently?我知道我的查询正在执行 CREATE,而在演示文稿中它们仅更新已加载的数据集,但我无法想象这就是我的堆使用率如此之高的原因。
谢谢
我的问题是,虽然使用了apoc.periodic.iterate,但我仍然将那个130万节点的大数据集上传到数据库作为查询的参数!
如下修改我的代码以自己进行批处理解决了我的堆使用问题和缓慢问题:
const int batchSize = 2000;
for (int count = 0; count < nodeData.Count; count += batchSize)
{
string createNodesQueryString = $@"
UNWIND $nodes_in AS newNodeObj
CREATE(n:MyNode)
SET n = newNodeObj";
int length = Math.Min(batchSize, nodeData.Count - count);
var createNodesResCursor = await session.RunAsync(createNodesQueryString,
new { nodes_in = nodeData.ToList().GetRange(count, length) });
var createNodesResSummary = await createNodesResCursor.ConsumeAsync();
}
我正在尝试使用 apoc.periodic.iterate 在 Neo4j 数据库中执行非常大的事务时减少堆使用。 我一直在遵循 this presentation. 中给出的建议 但是,我的结果与那些幻灯片中观察到的结果不同。
首先,关于我的设置的一些注意事项:
- 使用 Neo4j Desktop,Graph 版本 4.0.3 Enterprise,带有 APOC 4.0.0.10
- 我正在使用 .NET Neo4j 驱动程序 4.0.1 版调用查询。
- neo4j.conf 值:
- dbms.memory.heap.initial_size=2g
- dbms.memory.heap.max_size=4g
- dbms.memory.pagecache.size=2g
这是我运行宁的密码查询:
CALL apoc.periodic.iterate(
"UNWIND $nodes AS newNodeObj RETURN newNodeObj",
"CREATE(n:MyNode)
SET n = newNodeObj",
{batchSize:2000, iterateList:true, parallel:false, params: { nodes: $nodes_in } }
)
以及C#的行:
var createNodesResCursor = await session.RunAsync(createNodesQueryString, new { nodes_in = nodeData });
其中 createNodesQueryString
是上面的查询,nodeData
是一个 List<Dictionary<string, object>>
,其中每个字典只有三个条目:2 个字符串,1 个长。
当尝试 运行 创建 130 万个节点时,我观察到堆使用量(通过 JConsole)一直上升到 4GB 可用空间,并在 ~2.5g - 4g 之间来回跳动。减小批处理大小没有明显的区别,而提高 heap.max_size 会导致堆使用量猛增到几乎与该值一样多。它也真的很慢,需要 30 多分钟才能创建那 130 万个节点。
有谁知道我可能会对链接的演示文稿做什么 wrong/differently?我知道我的查询正在执行 CREATE,而在演示文稿中它们仅更新已加载的数据集,但我无法想象这就是我的堆使用率如此之高的原因。
谢谢
我的问题是,虽然使用了apoc.periodic.iterate,但我仍然将那个130万节点的大数据集上传到数据库作为查询的参数!
如下修改我的代码以自己进行批处理解决了我的堆使用问题和缓慢问题:
const int batchSize = 2000;
for (int count = 0; count < nodeData.Count; count += batchSize)
{
string createNodesQueryString = $@"
UNWIND $nodes_in AS newNodeObj
CREATE(n:MyNode)
SET n = newNodeObj";
int length = Math.Min(batchSize, nodeData.Count - count);
var createNodesResCursor = await session.RunAsync(createNodesQueryString,
new { nodes_in = nodeData.ToList().GetRange(count, length) });
var createNodesResSummary = await createNodesResCursor.ConsumeAsync();
}