Cypher - unlimited path length and large path length queries hang
我正在使用Neo4j Community 4.0.4。
我使用Python的官方Bolt驱动程序遇到了此问题,但在Neo4j浏览器(版本4.0.7)中也可以完全重现。
我现在有一个非常简单的图,由以下节点和关系类型组成:
1 2 | (:Document)-[:contains]->(:Block) (:Block)<-[:prev]-(:Block)-[:next]->(:Block) |
目前我的整个测试数据库中只有75个节点-1个Document节点和74个Block节点。
运行以下Cypher语句会使CPU达到100%,并且内存利用率无限期增加,之后我必须终止该会话:
1 2 3 | match (d:Doc{name: 'doc name'}) optional match (d)-[*]-(n) return d,n |
在某些时候我也遇到了Java堆大小错误。
仅当我在关系上设置严格的上限或指定方向时,它才能开始工作,例如:
1 | optional match (d)-[*..5]->(n) |
例如,这已经行不通了(答案要花很多时间,所以我必须取消会话):
1 | optional match (d)-[*..5]-(n) |
考虑到(a)我正在执行严格的局部图遍历,认为图数据库应该特别擅长,(b)与不同起始节点关联的群集未连接,并且(c)我的测试数据集很小,这怎么可能发生?
从这些症状看来,引擎在准备结果时似乎根本无法跟踪已访问过哪些节点和关系……还是我错过了什么?
更新:
Neo4j工作人员刚刚在Neo4j社区论坛上回答了这个问题:
https://community.neo4j.com/t/getting-paths-of-any-length-or-long-paths-does-not-work/18298
我错误地认为Cypher只会动态地从路径唯一性遍历切换到节点唯一性遍历,因为匹配之后的操作仅处理节点而不处理关系。
我的假设很差-不仅Cypher不会自动执行此操作,而且如果遍历路径中的所有节点,遍历核心Cypher的ATALL也无法删除路径。
建议使用基于APOC的解决方案:
1 2 3 | match (d:Doc{name: 'doc name'}) CALL apoc.path.subgraphNodes(d, {}) YIELD node as n return d, n |
在我的情况下,我断开了子图的连接,每个子图都是成千上万个节点,并且相对密集。尝试删除(:Doc)节点及其连接的所有对象之前,这会在将新版本的子图重新加载到Neo4j中时出现:
1 | disconnect delete d, n |
我将"重新加载之前删除旧版本"这一任务视为许多人在用例中可能遇到的子图的常见操作...安装和管理其他库(例如APOC或Graph Data Science库)似乎对于这种简单的事情来说是一个过大的杀伤力...但这是为了使删除变得更有针对性。
主要要考虑的是可变长度关系模式具有指数(时间和内存)复杂性。如果要遍历的节点平均具有