如何在具有多种关系的节点上优化Neo4j MERGE查询?

时间:2015-06-19 05:08:22

标签: neo4j cypher

我有一个图表,其中包含许多传出关系的节点。随着我添加更多关系,添加新的传出关系所花费的时间会降低。降级似乎是由于检查关系尚未存在所花费的时间(我使用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 个答案:

答案 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