这些查询在逻辑上等效,返回相同的6个结果(除了最后只返回5个结果),但性能差异很大,从31毫秒到45秒不等。我使用的是Neo4j 2.0.2。我有一个索引ON:SEGMENT(propertyId),但查找(n)不是查询速度慢的原因。
match (n {productId:6122})<-[:PARENT_OF*]-(p) return n,p;
[...]
6 rows
43879 ms
match (n:SEGMENT {productId:6122})<-[:PARENT_OF*]-(p) return n,p;
[...]
6 rows
44926 ms
start n=node(111426) match (n)<-[:PARENT_OF*]-(p) return n,p;
[...]
6 rows
31 ms
match (n {productId:6122}) match path=(n)<-[:PARENT_OF*]-(p) return path;
[...]
6 rows
694 ms
match (n:SEGMENT {productId:6122}) match path=(n)<-[:PARENT_OF*]-(p) return path;
[...]
6 rows
161 ms
match (n:SEGMENT)<-[:PARENT_OF*]-(p:SEGMENT) where n.productId=6122 return n,p;
[...]
5 rows
45332 ms
添加了PROFILE输出:
PROFILE match (n:SEGMENT {productId:6122})<-[:PARENT_OF*]-(p:SEGMENT) return n,p;
`ColumnFilter(symKeys=["n", "p", " UNNAMED34"], returnItemNames=["n", "p"], _rows=5, _db_hits=0)
Filter(pred="(hasLabel(n:SEGMENT(0)) AND Property(n,productId(9)) == Literal(6122))", _rows=5, _db_hits=1895169)
TraversalMatcher(start={"label": "SEGMENT", "producer": "NodeByLabel", "identifiers": ["p"]}, trail="(p)-[:PARENT_OF*1..]->(n)", _rows=1895169, _db_hits=1895169)`
PROFILE match (n {productId:6122}) match path=(n)<-[:PARENT_OF*]-(p) return path;
`ColumnFilter(symKeys=["n", "p", " UNNAMED41", "path"], returnItemNames=["path"], _rows=6, _db_hits=0)
ExtractPath(name="path", patterns=["ParsedVarLengthRelation( UNNAMED41,Map(),ParsedEntity(n,n,Map(),List()),ParsedEntity(p,p,Map(),List()),List(PARENT_OF),INCOMING,false,None,None,None)"], _rows=6, _db_hits=0)
PatternMatcher(g="(n)-[' UNNAMED41']-(p)", _rows=6, _db_hits=0)
Filter(pred="Property(n,productId(9)) == Literal(6122)", _rows=1, _db_hits=48531)
AllNodes(identifier="n", _db_hits=48531, _rows=48531, identifiers=["n"], producer="AllNodes")`
答案 0 :(得分:2)
最快的查询是内部ID查找,这并不奇怪。 ID值本身(避免将其作为外部标识符)与存储的数据结构紧密耦合。它大致相当于告诉Cypher节点在节点存储文件中的位置。 (*)
对于接下来的两个最快的,我可能完全错误,但我认为它们更快,因为你只匹配路径,虽然我不确定这究竟是如何影响查询的行为。 两者之间的小增量可以通过以下事实来解释:一个查询在引擎盖下使用模式索引,而另一个不是(因为标签在第二种情况下未指定)。
对于最后3个,可能与起点PARENT_OF的深度相比,起点位置查找时间非常无关紧要。你最终可能会走很长的路,我不确定。
(*)我仍然不明白如何通过起始节点的ID来查找与类似的2个最慢查询(它们也不会通过路径匹配......)的差异。