我有一个像这样的查询作为我的应用程序的关键组件:
MATCH (group:GroupType)
WHERE group.Name = "String"
MATCH (node:NodeType)
WHERE (node)-[:MEMBER_OF]->(group)
RETURN node
:GroupType(Name) 上有索引
在大约包含 10,000 个元素的数据库中,此查询使用近 100 万次数据库命中。这是查询的PROFILE
:
但是,执行相同搜索的查询的这种细微变化要快得多:
MATCH (group:GroupType)
WHERE group.Name = "String"
MATCH (node:NodeType)-[:MEMBER_OF]->(group)
RETURN node
唯一的区别是 node:NodeType
匹配和关系匹配合并为单个 MATCH
而不是 MATCH ... WHERE
。尽管执行相同的搜索,此查询使用前一个查询的数据库命中数的 1/70,并且速度快了 10 倍以上:
我认为 Cypher 将 MATCH ... WHERE 语句视为单个搜索表达式,因此这两个查询应该编译为相同的操作,但这两个查询似乎执行截然不同的操作。这是为什么?
最佳答案
首先我想说这实际上并不是一个 Cypher 问题。 Cypher 描述了您想要什么,而不是如何获取它,因此该查询的性能在 Neo4J 3.1.1 和 Neo4J 3.2.3 之间差异很大。
由于执行 Cypher 的人决定如何执行此操作,真正的问题是“为什么 Neo4J Cypher 规划器不以相同的方式对待这些?”
理想情况下,这两个 Cyphers 应该等同于
MATCH (node:NodeType)-[:MEMBER_OF]->(group:GroupType{name:"String"})
RETURN node
因为它们都应该产生相同的结果。
实际上,动态解析具有大量“等效”表达式的查询存在许多微妙的细微差别。但是,上下文的微妙变化可能会改变这种等价性,比如说,如果您进行了此调整
MATCH (group:GroupType)
WHERE group.Name = "String"
MATCH (node:NodeType)
WHERE (node)-[:MEMBER_OF]->(group) OR SIZE(group.members) = 1
RETURN node
现在这两个查询的结果几乎没有相似之处。为了扩展,查询规划器必须制定决策捷径,以便尽快制定有效的计划。
在某种程度上,性能取决于您所运行的服务器正在运行的内容,因为为一种语言提出一个可操作的查找策略,让您可以请求任何/所有内容是很困难的!
相关阅读
关于performance - 为什么这两个看似相同的 Cypher 查询在速度上差异如此之大?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45742527/