2016-11-21 191 views
3

我在努力高效地批量更新Neo4j中的关系属性。目的是更新〜500000的关系(每个具有大约3个属性),其余块成在单一的Cypher语句1000和处理批次,Neo4j中缓慢的性能批量更新关系属性

UNWIND {rows} AS row 
MATCH (s:Entity) WHERE s.uuid = row.source 
MATCH (t:Entity) WHERE t.uuid = row.target 
MATCH (s)-[r:CONSUMED]->(t) 
SET r += row.properties 

然而1000个节点的每个批次需要大约60秒。存在的:Entity标签上UUID性的指标,即我先前曾执行过,

CREATE INDEX ON :Entity(uuid) 

这意味着匹配关系是每个查询计划的超高效,

enter image description here

有总共有6个数据库命中,查询在〜150毫秒内执行。我还添加上确保了每场比赛只返回一个元素的UUID属性唯一性约束,

CREATE CONSTRAINT ON (n:Entity) ASSERT n.uuid IS UNIQUE 

有谁知道我可以继续调试明白为什么它采取的Neo4j这么长时间来处理的关系?

请注意,我正在使用类似的逻辑来更新节点,它的速度要快几个数量级,并且有更多的元数据与它们相关联。

仅供参考我正在使用Neo4j 3.0.3,py2neo和Bolt。的Python代码块的形式为,

for chunk in chunker(relationships): # 1,000 relationships per chunk 
    with graph.begin() as tx: 
     statement = """ 
      UNWIND {rows} AS row 
      MATCH (s:Entity) WHERE s.uuid = row.source 
      MATCH (t:Entity) WHERE t.uuid = row.target 
      MATCH (s)-[r:CONSUMED]->(t) 
      SET r += row.properties 
      """ 

      rows = [] 

      for rel in chunk: 
       rows.append({ 
        'properties': dict(rel), 
        'source': rel.start_node()['uuid'], 
        'target': rel.end_node()['uuid'], 
       }) 

      tx.run(statement, rows=rows) 

回答

2

尝试此查询:

UNWIND {rows} AS row 
WITH row.source as source, row.target as target, row 
MATCH (s:Entity {uuid:source}) 
USING INDEX s:Entity(uuid) 
WITH * WHERE true 
MATCH (t:Entity {uuid:target}) 
USING INDEX t:Entity(uuid) 
MATCH (s)-[r:CONSUMED]->(t) 
SET r += row.properties; 

它使用index hints强制索引查找为两个Entity节点,然后一个Expand(Into)运算符,它应当更比查询计划中显示的Expand(All)Filter运算符高。

0

@ william-lyon我想知道我是否需要WITH * WHERE true子句?我想问的原因是DB的命中数为4〜8的增加,即

PROFILE 
MATCH (s:Entity {uuid:row.source}) 
USING INDEX s:Entity(uuid) 
MATCH (t:Entity {uuid:row.target}) 
USING INDEX t:Entity(uuid) 
MATCH (s)-[r:CONSUMED]->(t) 

回报

PROFILE 
MATCH (s:Entity {uuid:row.source}) 
USING INDEX s:Entity(uuid) 
WITH * WHERE true 
MATCH (t:Entity {uuid:row.target}) 
USING INDEX t:Entity(uuid) 
MATCH (s)-[r:CONSUMED]->(t) 

回报

请注意,使用索引提示可将数据库命中数从6降低到4.对于上下文,我们有多个节点标签(和索引),尽管每个节点都有:Entity标签。