我有一个图表,其节点具有许多传出关系 . 随着我添加更多关系,添加新的传出关系所花费的时间会降低 . 退化似乎是由于检查关系尚未存在所花费的时间(我使用MERGE来添加关系) .
关系的目标节点本身关系很少 . 有什么方法可以强制Neo4j检查目标节点而不是源节点是否存在关系?
这是重现问题的测试脚本 . 它创建一个id为0的节点,后跟由 HAS
关系连接到节点0的1000个节点 . 随着节点的添加,执行时间会线性增加 .
CREATE CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE
UNWIND RANGE(1,1000) AS i
MERGE (from:Node { id: 0 })
MERGE (to:Node { id: i})
MERGE (from)-[:HAS]->to
添加了1001个标签,创建了1001个节点,设置了1001个属性,创建了1000个关系,语句在3496毫秒内执行 .
UNWIND RANGE(1001,2000) AS i
MERGE (from:Node { id: 0 })
MERGE (to:Node { id: i})
MERGE (from)-[:HAS]->to
添加了1000个标签,创建了1000个节点,设置了1000个属性,创建了1000个关系,语句在7030毫秒内执行 .
UNWIND RANGE(2001,3000) AS i
MERGE (from:Node { id: 0 })
MERGE (to:Node { id: i})
MERGE (from)-[:HAS]->to
添加了1000个标签,创建了1000个节点,设置了1000个属性,创建了1000个关系,语句在10489毫秒内执行 .
UNWIND RANGE(3001,4000) AS i
MERGE (from:Node { id: 0 })
MERGE (to:Node { id: i})
MERGE (from)-[:HAS]->to
添加了1000个标签,创建了1000个节点,设置了1000个属性,创建了1000个关系,语句在14390毫秒内执行 .
如果使用 CREATE
而不是 MERGE
,性能会好得多 . 我不能使用 CREATE
,因为我想确保关系是唯一的 .
UNWIND RANGE(4001,5000) AS i
MERGE (from:Node { id: 0 })
MERGE (to:Node { id: i})
CREATE (from)-[:HAS]->to
添加了1000个标签,创建了1000个节点,设置了1000个属性,创建了1000个关系,语句在413毫秒内执行 .
注意:使用Neo4j v2.2.2进行测试
1 回答
这是因为在执行合并时,cypher还不够聪明地使用节点的程度 . 在用于读取的COST优化器中,它已经很聪明,但是对于更新,使用了旧的RULE优化器 .
使用
CREATE UNIQUE
而不是MERGE
尝试使用在COST中使用get-degree的路径表达式之后,使用它改变了从&到的顺序我记得
shortestPath
实际上考虑了学位,也从左到右所以我试着将它与
CREATE
结合起来,并且效果非常好,这里有100.000个节点的例子 .