我有一个图表,其中包含许多传出关系的节点。随着我添加更多关系,添加新的传出关系所花费的时间会降低。降级似乎是由于检查关系尚未存在所花费的时间(我使用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进行测试
答案 0 :(得分:10)
这是因为在执行合并时,cypher还不够聪明地使用节点的程度。在用于读取的COST优化器中,它已经很聪明,但是对于更新,使用旧的RULE优化器。
玩了一会儿之后有点失败
*改变&的顺序至
*使用CREATE UNIQUE
代替MERGE
*尝试使用在COST中使用get-degree的路径表达式
我记得shortestPath
实际上考虑了学位,也从左到右
因此我尝试将其与CREATE
结合使用,效果非常好,
这是100.000个节点的示例。
neo4j-sh (?)$ CREATE CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE;
+-------------------+
| No data returned. |
+-------------------+
Constraints added: 1
1054 ms
neo4j-sh (?)$
neo4j-sh (?)$ UNWIND RANGE(0,100000) AS i CREATE (to:Node { id: i});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 100001
Properties set: 100001
Labels added: 100001
2375 ms
neo4j-sh (?)$
neo4j-sh (?)$
neo4j-sh (?)$ MATCH (from:Node { id: 0 })
> UNWIND RANGE(1,100000) AS i
> MATCH (to:Node { id: i})
> WHERE shortestPath((to)<-[:HAS]-(from)) IS NULL
> CREATE (from)-[:HAS]->(to);
+-------------------+
| No data returned. |
+-------------------+
Relationships created: 100000
2897 ms
neo4j-sh (?)$
neo4j-sh (?)$
neo4j-sh (?)$ MATCH (from:Node { id: 0 })
> UNWIND RANGE(1,100000) AS i
> MATCH (to:Node { id: i})
> WHERE shortestPath((to)<-[:HAS]-(from)) IS NULL
> CREATE (from)-[:HAS]->(to);
+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+
2360 ms