代码之家  ›  专栏  ›  技术社区  ›  John

Neo4j中的性能批量更新关系属性缓慢

  •  5
  • John  · 技术社区  · 8 年前

    我正在努力有效地批量更新Neo4j中的关系属性。目标是更新约500000个关系(每个关系大约有3个属性),我将其分为1000个批次,并在单个密码语句中进行处理,

    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秒。的UUID属性上存在索引 :Entity

    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 回复  |  直到 8 年前
        1
  •  2
  •   William Lyon    8 年前

    尝试此查询:

    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 查询计划显示的运算符。

        2
  •  0
  •   John    8 年前

    @威廉·里昂:我想知道我是否需要 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 标签