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

我在努力有效地批量更新Neo4j中的关系属性.目标是更新~500,000个关系(每个关系大约有3个属性),我将这些关系分成1,000个批处理并在单个Cypher语句中处理,

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

但每批1,000个节点大约需要60秒.在:Entity标签的UUID属性上有一个索引,即我以前运行过,

CREATE INDEX ON :Entity(uuid)

这意味着根据查询计划匹配关系是非常有效的,

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

共有6个db命中,查询在~150 ms内执行.我还在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)

最佳答案 试试这个查询:

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运算符更高效.

点赞