【问题标题】:Erratic behavior of Neo4j while loading datas加载数据时 Neo4j 的不稳定行为
【发布时间】:2017-08-22 16:07:26
【问题描述】:

我们在 Neo4j 服务器中加载数据,该服务器主要表示(几乎)k-ary 树,在大多数情况下 k 介于 2 和 10 之间。我们有大约 50 种可能的节点类型,以及大约相同数量的关系类型。 服务器在线,可以从多个实例加载数据(所以,很遗憾,我们不能使用 neo4j-import)

对于大约 100 000 个节点和关系,我们的加载速度非常慢,在一台好的机器上加载大约需要 600 万。有时我们会遇到需要 4000 万次加载相同的数据!看看neo4j进程,它有时什么都不做...... 在这种情况下,我们会收到如下消息:

WARN [o.n.k.g.TimeoutGuard] 事务超时。 (超时:1481 毫秒)。

此外,尽管结构非常复杂,但我们不会遇到查询快速执行的问题

我们加载数据如下:

一个密码文件是这样加载的:

neo4j-shell -host localhost -v -port 1337 -file myGraph.cypher

密码文件包含几个部分:

  1. 约束创作:

    CREATE CONSTRAINT ON (p:MyNodeType) ASSERT p.uid IS UNIQUE;

  2. 在非常少的节点集上建立索引(10 个以上)

    我们仔细选择这些以避免反性能行为。

    CREATE INDEX ON :MyNodeType1(uid);

  3. 节点创建

    USING PERIODIC COMMIT 4000 LOAD CSV WITH HEADERS FROM "file:////tmp/my.csv" AS csvLine CREATE (p:MyNodeType1 {Prop1: csvLine.prop1, mySupUUID: toInt(csvLine.uidFonctionEnglobante), lineNum: toInt(csvLine.lineNum), uid: toInt(csvLine.uid), name: csvLine.name, projectID: csvLine.projectID, vValue: csvLine.vValue});

  4. 建立关系

    LOAD CSV WITH HEADERS FROM "file:////tmp/RelsInfixExpression-vLeftOperand-SimpleName_javaouille-normal-b11695.csv" AS csvLine Match (n1:MyNodeType1) Where n1.uid = toInt(csvLine.uidFather) With n1, csvLine Match (n2:MyNodeType2) Where n2.uid = toInt(csvLine.uidSon) MERGE (n1)-[:vOperandLink]-(n2);

问题 1

我们在加载数据时有时会在 Neo4j 服务器中遇到 OOM,即使使用相同的数据也很难重现。但是最近在关系加载命令中添加了USING PERIODIC COMMIT 1000,我们从未重现过这个问题。这可能是OOM问题的解决方案吗?

问题 2

Periodic Commit 参数好吗? 还有其他方法可以加快数据加载速度吗? IE。编写数据加载脚本的另一种策略?

问题 3

有没有办法防止超时?用另一种方式来编写数据加载脚本或者 JVM 调优?

问题 4

几个月前,我们将密码脚本拆分为 2 或 3 部分以同时启动它,但我们停止了这种做法,因为服务器经常弄乱数据并变得无法使用。有没有办法“干净地”拆分脚本并同时启动它们?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    问题1:是的,USING PERIODIC COMMITLOAD CSV 导致OOM 错误时首先尝试的。

    问题 2 和 3:定期提交批量大小的“最佳位置”取决于您的 Cypher 查询、您的数据特征以及 Neo4j 服务器的配置方式(所有这些都可能随时间而变化)。您不希望批量大小太高(以避免偶尔出现 OOM),也不希望太低(以避免减慢导入速度)。你也应该tune the server's memory configuration。但是您必须自己进行实验才能发现最佳批量大小和服务器配置,并根据需要进行调整。

    问题 4:必须避免触及相同节点和/或关系的并发写入操作,因为它们可能导致错误(如死锁和违反约束)。如果您可以拆分您的操作,以便它们作用于完全不相交的子图,那么它们应该能够同时运行而不会出现此类错误。

    此外,您应该PROFILE 您的查询以查看服务器将如何实际执行它们。例如,即使 :MyNodeType1(uid):MyNodeType2(uid) 都被索引(或具有唯一性约束),这并不意味着 Cypher 规划器在执行最后一个查询时会自动使用这些索引。如果您对该查询的配置文件显示它没有使用索引,那么您可以向查询添加提示以使规划器(更有可能)使用它们:

    LOAD CSV WITH HEADERS FROM "file:////tmp/RelsInfixExpression-vLeftOperand-SimpleName_javaouille-normal-b11695.csv" AS csvLine 
    MATCH (n1:MyNodeType1) USING INDEX n1:MyNodeType1(uid)
    WHERE n1.uid = TOINT(csvLine.uidFather)
    MATCH (n2:MyNodeType2) USING INDEX n2:MyNodeType2(uid)
    WHERE n2.uid = TOINT(csvLine.uidSon)
    MERGE (n1)-[:vOperandLink]-(n2);
    

    另外,如果可以将uid值存储为字符串,可以去掉TOINT()的使用。这样会在一定程度上加快速度。

    【讨论】:

      猜你喜欢
      • 2023-04-10
      • 2015-10-09
      • 2014-09-26
      • 2011-01-27
      • 2019-08-02
      • 1970-01-01
      • 2012-04-24
      • 1970-01-01
      • 2023-01-30
      相关资源
      最近更新 更多