加载数据时Neo4j的不稳定行为

时间:2017-08-22 16:07:27

标签: neo4j cypher

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

我们遇到大约10万个节点和关系的非常慢的加载,这需要大约6百万加载到一台好机器。有时我们会遇到相同数据的加载,这需要4000万!看看neo4j进程,它有时什么都不做...... 在这种情况下,我们有以下消息:

  

WARN [o.n.k.g.TimeoutGuard]交易超时。 (加班:1481毫秒)。

除了非常复杂的结构之外,我们不会遇到查询问题,这些问题可以快速执行

我们按如下方式加载数据:

cypher文件加载如下:

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

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);

  5. 问题1

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

    问题2

    Periodic Commit参数是否良好? 还有另一种加速数据加载的方法吗? IE浏览器。编写数据加载脚本的另一种策略是什么?

    问题3

    有办法防止超时吗?用另一种方法编写数据加载脚本或者可能是JVM调优吗?

    问题4

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

1 个答案:

答案 0 :(得分:2)

问题1:是的,当USING PERIODIC COMMIT导致OOM错误时,首先要尝试LOAD CSV

问题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()的使用。这将在一定程度上加快速度。