Neo4j 2.0 Cypher:跳过限制与范围()与收集(n)之间的差异与col [x..y]

时间:2014-02-28 14:10:54

标签: neo4j

当处理大批量并使用跳过/限制或范围时,我注意到(并且还有许多其他人),跳过/范围起始编号越高,性能似乎会降低很多。

我想知道使用collect(n)作为col [x..y]时是否有性能提升?

我已经尝试过了。我也不确定他们是否会以相同的顺序返回相同的节点。

假设我的总计数为(n:LotsOfNodes),并且我以500个批次发送以下cypher查询:

MATCH (n:LotsOfNodes) WHERE has(n.OtherNodeId)
WITH collect(n) as AllNodes
WITH AllNodes[30000..30500] as rangeNodes
FOREACH (a in rangeNodes | 
  MERGE (b:OtherNode {id:a.OtherNodeId})
  MERGE (a)-[r:RELATE_A_TO_B]->(b)
)

以上是否涉及相同的节点:

MATCH (a:LotsOfNodes)
,(b:OtherNode {id:a.OtherNodeId})
WITH a,b SKIP 30000 LIMIT 500
MERGE (a)-[r:RELATE_A_TO_B]->(b)

MATCH (a:LotsOfNodes) WHERE has(a.OtherNodeId)
WITH collect(n) as AllNodes
FOREACH (i in range(30000,30500) |
 FOREACH (a in [AllNodes[i]] | 
   MERGE (b:OtherNode {id:a.OtherNodeId})
   MERGE (a)-[r:RELATE_A_TO_B]->(b)
 )
)

我已经尝试了所有这三个查询,并且在使用skip / range时遇到了一些严重的性能问题,或者在我取出WHERE子句时出错。有时(a)没有属性OtherNodeId,因为在导入期间它已设置为null

第一个查询的要点是看是否存在性能问题,并且在大多数情况下,它似乎很好(但现在我担心我实际上并没有抓住所有节点)。

另一个奇怪的事情是,有时候,它每批500(<500毫秒)运行速度很快,而其他时候每批需要高达42秒。 42秒问题总是出现在同一个(:标签)上,所以它可能是该节点中属性的奇怪之处,但我无法弄清楚...我要查询的属性都是索引和设置独一无二。


根据Wes的评论编辑:尝试查看是否将每个列表作为参数传递可能有助于提高性能 - 其中[listTarget]是批处理的,但[listSource]始终在完整列表中发送:

FOREACH (x in [listTarget] | 
  FOREACH (n in [listSource] | 
    MERGE (s:SourceLabel {sourceId : x.sourceId} )
    -[r:RELATIONTYPE]->
    (t:TargetLabel {targetId : x.targetId}) 
    SET s = n, t = x, r.sourceId = s.sourceId , r.targetId = t.targetId 
))

1 个答案:

答案 0 :(得分:3)

以下是几点。对不起,它不是更彻底,但它太大了,不适合评论,所以这是一个简短的答案。

  1. range()只是简单地生成一个集合(它根本没有点击文件),所以它通常是一个快速的操作。
  2. SKIP / LIMIT不应该在没有ORDER BY和一些唯一键的情况下使用(如果你没有更好的,请使用节点id)。 SKIP / LIMIT不保证ORDER,如果您在运行时将新记录添加到同一标签,则特别不可能。
  3. 我感觉MERGE的减速是OtherNode已经存在的情况。 CREATE比MATCH更快。我可能错了,但是42秒似乎非常长。你可以在那段时间查看messages.log,看看是不是发生了奇怪的事情?
  4. 在2.1中他们发布了一个新的Cypher功能:PERIODIC COMMIT,它可以解决其中一些问题。