【发布时间】:2015-04-08 03:28:19
【问题描述】:
我正在寻找一个快速的 Cypher 语句,它返回一组已知节点(我有他们的 Neo4j ID)之间的所有关系,以便我可以为该特定节点集组装子图。我在一个名为 label 的标签中工作,它有大约 50K 节点和这些节点之间的 800K 边。
对此我有几种工作方法,但对于我的应用程序来说,没有一种方法足够快,即使是在较小的集合大小(少于 1000 个节点)时也是如此。
例如,以下语句可以解决问题:
MATCH (u:label)-[r]->(v:label)
WHERE (ID(u) IN {ids}) AND (ID(v) IN {ids})
RETURN collect(r)
{ids} 是作为 Py2Neo cypher.execute(statement, parameters) 方法的参数提供的数字 Neo4j id 的列表。问题是一组 838 个节点需要大约 34 秒,它返回它们之间的所有 19K 关系。我意识到该图有点密集,但每返回 1000 条边需要 1.76 秒。我只是不认为这是可以接受的。
如果我改用 START 子句(如下所示),时间实际上会差一些。
START u=node({ids}), v=node({ids})
MATCH (u:label)-[r]->(v:label)
RETURN collect(r)
我发现了许多类似的问题/答案,但它们在某些方面都不尽如人意。有没有更好的说明,甚至更好的图形模式,以便它可以扩展到数千个节点的集合?
更新
感谢您的快速回复。首先,要运行我当前对 528 个节点的查询作为输入 (len(ids)=528),它需要 32.1 秒,查询计划如下。
NodeByIdSeek: 528 hits
Filter : 528 hits
Expand(All) : 73,773 hits
Filter : 73,245 hits
Projection : 0 hits
Filter : 0 hits
Brian Underwood 的查询使用相同的输入,需要 27.8 秒。查询计划是相同的,除了最后两个步骤(投影和过滤器),他的查询不存在这些步骤。但是 db hits sum 是一样的。
Michael Hunger 的查询耗时 26.9 秒,查询计划与 Brian 的查询相同。
我在实验之间重新启动了服务器以避免缓存影响(可能有更聪明的方法来做到这一点)。我还直接从 Web 界面查询,以绕过我的代码和我正在使用的库中可能存在的瓶颈。
底线,Neo4j 似乎足够聪明,可以优化我的查询,但是即使是相当小的集合,它仍然很慢。有什么建议吗?
【问题讨论】:
-
将第一行改成
MATCH (u:label)-[r]-(v:label)会有性能变化吗? -
你能分享你的查询计划吗?您可以通过在查询前加上
PROFILE来获取它 -
不返回 collect(r) 只是 r
-
你的用例是什么? (你当然不能显示这个图表)也许你应该改变你的策略,只得到你处理的图表部分?如果你让我知道你的目标是什么,帮助会更容易
-
@jag426 对于 528 个节点的相同输入,它花费了 7 倍的时间。我还必须处理重复项。
标签: performance neo4j cypher