如何使用连接提示避免代价高昂的遍历
使用 Cypher 匹配模式时,要评估的可能路径数量通常与查询执行时间相关。
当路径中存在超级节点(一个具有大量关系且其类型包含在 MATCH 模式中的节点),或者只是有足够多的具有大量关系的节点时,可能路径的数量可能会激增,从而降低查询速度。通过超级节点进行这种遍历可能会非常昂贵。
有时,在遍历某些类型的模式时,您可能从您的模型中知道,如果可能的话,两种特定类型的节点之间的关系应该以特定方向而不是相反方向进行遍历以获得最佳性能,对于超级节点来说,这种情况经常发生。
例如,如果我们有一个 :People 喜欢音乐艺术家 :Artist 的社交图,那么很有可能其中一些艺术家(也许很多)是超级节点。如果我们正在查看 (:Person)-[:LIKES]→(:Artist {name:'Britney Spears'})
,我们可以合理地假设一个 :Person 可能只有相对较少的 :LIKES 关系,也许少于 100 个,但是像 Britney Spears 这样受欢迎的 :Artist 可能有数百万个 :LIKES 关系指向她。
遍历 Britney Spears 将会很昂贵,因为它可能会将可能路径的数量乘以 :LIKES 关系的数量,从而导致查询执行时间爆炸。但是,仅遍历 **到** Britney Spears 的路径可能会相对便宜。
在查询有多个起点并且计划程序在考虑通过超级节点进行不良遍历的情况下没有提供有效计划的情况下,您可以在查询中使用 连接提示 来防止遍历某个节点。
相反,将使用多个起点,并从每个起点开始扩展,直到到达连接提示中指定的节点。然后,使用哈希连接查找从两个方向匹配到的公共节点,并实现完全匹配的路径。
如果我试图找出我和我的朋友共同喜欢的艺术家(以及共同喜欢的数量),我可能会使用这样的查询
MATCH (me:Person {name:'Me'})-[:FRIENDS_WITH]-(friend)-[:LIKES]->(a:Artist)<-[:LIKES]-(me)
RETURN a, count(a) as likesInCommon
如果计划程序决定仅对该查询使用单个起点并且没有识别出潜在的超级节点问题,那么它可能会选择计划通过 :Artist 节点进行扩展,这可能会非常昂贵

由于 Cypher 查询计划程序能够重新排列相邻 MATCH 模式的顺序(以及跨越某些 WITH 子句),因此仅重新排列我的模式是不够的。我可以使用连接提示来确保我们仅遍历 **到** 有问题的节点,而不是遍历它或远离它。
MATCH (me:Person {name:'Me'})-[:FRIENDS_WITH]-(friend)-[:LIKES]->(a:Artist)<-[:LIKES]-(me)
USING JOIN on a
RETURN a, count(a) as likesInCommon
从查询计划中,我们可以看到,从同一个起点,我们遍历了两个不同的路径到达 a
,但没有遍历它,并执行节点哈希连接以在公共艺术家节点上统一路径。

此页面是否有帮助?