1

在 Neo4j 数据库中执行非常大的事务时,我正在尝试使用 apoc.periodic.iterate 来减少堆使用量。我一直在遵循本演示文稿中给出的建议。 但是,我的结果与那些幻灯片中观察到的结果不同。

首先,关于我的设置的一些注意事项:

  • 使用 Neo4j Desktop,图形版本 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 万个节点。

有谁知道我对链接的演示文稿可能做错了什么/有什么不同?我知道我的查询正在执行 CREATE,而在演示文稿中他们只是更新已经加载的数据集,但我无法想象这就是我的堆使用率如此之高的原因。

谢谢

4

1 回答 1

1

我的问题是,尽管使用了 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();
  }
于 2020-05-18T14:47:44.983 回答