我有一个图表,其节点具有许多传出关系.随着我添加更多关系,添加新的传出关系所花费的时间会降低.退化似乎是由于检查关系尚未存在所花费的时间(我使用MERGE来添加关系).
关系的目标节点本身关系很少.有什么方法可以强制Neo4j检查目标节点而不是源节点是否存在关系?
这是重现问题的测试脚本.它创建一个id为0的节点,后跟1000个通过该HAS关系连接到节点0的节点.随着节点的添加,执行时间会线性增加.
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
Run Code Online (Sandbox Code Playgroud)
添加了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
Run Code Online (Sandbox Code Playgroud)
添加了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
Run Code Online (Sandbox Code Playgroud)
添加了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
Run Code Online (Sandbox Code Playgroud)
添加了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
Run Code Online (Sandbox Code Playgroud)
添加了1000个标签,创建了1000个节点,设置了1000个属性,创建了1000个关系,语句在413毫秒内执行.
注意:使用Neo4j v2.2.2进行测试
Mic*_*ger 10
这是因为在执行合并时,cypher还不够聪明地使用节点的程度.在用于读取的COST优化器中,它已经很聪明,但是对于更新,使用了旧的RULE优化器.
使用它后有点失败*改变from和to*的顺序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
Run Code Online (Sandbox Code Playgroud)