关于 neo4j 图中循环的性能影响?

On the performance impact of cycles in a neo4j graph?

图中的循环有多种形式。它们可以很短也可以很长。例如:peter -> bill -> tom -> peter;彼得 -> 彼得。有时循环的存在是不受欢迎的,但有时有必要以这种方式表示您的数据。

我想知道当 运行 在 Neo4j 中进行查询时,图形(我的数据)中存在循环会产生什么影响。

假设我查询我的数据的特定模式。可能存在我有循环的情况,也可能存在我的数据中没有循环的情况。因为,本质上,一个循环是一个无限循环(例如,如果我是 运行 一个 DFS 算法,如果我不采取预防措施,它将无限循环),我假设 Neo4j DBMS 配备了开销检测并打破这些循环。

出于这个原因,我相信在这些情况下会有显着的性能差异,即暗示没有循环会导致某些查询的性能更好。

我这样想对吗?这是一个有效的问题还是我在夸大其词? Neo4j 中有关于这个主题的 material 吗?

tl;dr

无限循环在 Cypher 中是不可能的,因此图表中的循环不会单独对查询性能造成问题。

详细的答案

这是一个很好的问题,答案的开头在 uniqueness within Cypher traversals 的文档中:

While pattern matching, Neo4j makes sure to not include matches where the same graph relationship is found multiple times in a single pattern. In most use cases, this is a sensible thing to do.

虽然更准确地说:

where the same graph relationship is found multiple times in a single path

由于根据匹配模式遍历路径,因此在该路径中只能遍历一次特定关系。遍历的方向在这里无关紧要。关系是否有分配给它的变量或者关系是否是可变长度路径的一部分也没有。一旦一个关系被单条路径遍历,它将永远不会被再次遍历。

这几乎可以保护您免受无限循环的影响,根据定义,无限循环要求您一遍又一遍地遍历相同的关系。

然而,当节点之间存在大量多条路径时,由于可以遍历的所有可能关系(每条路径都是唯一的并且从不重复)的排列,这并不能保护您免受成本上升的影响。

例如,如果您在 Neo4j 浏览器中从 :play movies 获取电影图表,您可以发出类似 MATCH (n:Person)-[*]-(m:Person) RETURN count(*) 的查询,这可能永远不会 return,因为数字任何两个 :Person 节点之间的可能路径,由于可以遍历的所有可能关系的排列(而不在每个单独的路径中重复任何关系)变得非常昂贵(并且这是针对两个 :Person 节点的所有可能组合完成的)图)。

这种类型的查询最终会锁定 Neo4j,因为要评估的路径数量会变成天文数字,但这同样不是由于无限循环造成的。

要绕过这些限制(毕竟,您可能希望使用非常相似的查询来查找可访问的不同节点,或可访问的不同节点的数量),您需要将遍历的唯一性从Cypher 的 'RELATIONSHIP_PATH' 对其他事物的独特性。

如果您正在使用 Java 中的遍历框架(如果您正在创建用户定义过程、内核扩展或使用嵌入式 Neo4j,则可以使用它),您可以更改 uniqueness of the traversal不同的行为。

关于避免无限循环,'NODE_PATH' 唯一性也将阻止它们,因为它确保每个单独的路径只能访问一个节点。

同时防止无限循环的最有用的方法之一是 'NODE_GLOBAL' 唯一性,它确保一个节点在所有路径 中总共只被访问一次 ,而不仅仅是每个小路。当您想找到从起始节点可达的所有不同节点(或计算所有不同节点)时,最好使用这种唯一性,因此我们在某些 path expander procs of the APOC Procedures 库中使用 'NODE_GLOBAL' 唯一性(并且在使用 apoc.path.expandConfig() 时,如果您想要不同的类型,您可以自己明确设置唯一性)。

所以总而言之,默认情况下使用 Cypher 不会发生无限循环。您遇到的一些更严重的 Cypher 性能问题可能与匹配匹配模式的可能路径数量激增有关,尤其是在无限制的可变长度扩展的情况下,因为这可能会耗尽堆 space 或以其他方式发展成要评估的独特路径数量非常多。通过遍历 API 或 APOC 路径扩展程序,您可以根据查询的需要更改遍历唯一性行为。