我们在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文件包含几个部分:
限制创作:
CREATE CONSTRAINT ON (p:MyNodeType) ASSERT p.uid IS UNIQUE;
非常少的节点索引(10以上)
我们仔细选择这些以避免反击表现行为。
CREATE INDEX ON :MyNodeType1(uid);
节点创作
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});
关系创作
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
几个月前,我们将cypher脚本拆分为2或3个部分以同时启动它,但我们停止了这一点,因为服务器经常弄乱数据并变得无法使用。有没有办法分开"干净"脚本并同时启动它们?
答案 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()
的使用。这将在一定程度上加快速度。