Cypher技巧:如何使用连接提示(Join Hints) 避免进行代价高昂的遍历

作者: 安德鲁·鲍曼(Andrew Bowman)

 

使用Cypher匹配模式时,要评估的可能路径数通常会影响到查询执行时间。

当路径中有一个超级节点(又称繁忙节点Dense Node,即一个具有大量关系的节点,其类型包含在MATCH查询中)时,或者仅仅是大量拥有许多关系的节点时,可能的路径数量会呈爆炸式增长,从而严重降低查询速度。 这种通过超节点进行的遍历通常很昂贵。

有时,当遍历某些类型的模式时,您可能已经通过建模中知道,如果可能的话,应该在特定方向上遍历特定类型的节点之间的关系,而不是相反,以获得最佳性能,超节点通常就属于这种情况。

例如,如果我们有一个:People类型节点的社交图谱,成员:LIKE喜欢音乐家,那么很可能其中一些艺术家(也许很多)是超级节点。如果我们这样查找模式:

(:Person)-[:LIKES]->(:Artist {name:'Britney Spears'})

不难想象指向多数:Person的LIKES的关系相对较少,也许少于100,但像布兰妮·斯皮尔斯(Britney Spears,“小甜甜”)这样的受欢迎的:Artist可能有成千上万的:LIKES关系指向她。

经过Britney Spears的遍历成本很大,因为它将可能的路径数量乘以:LIKES关系的数量,从而拖慢了查询的执行。但是,如果我们只是遍历到布兰妮·斯皮尔斯(Britney Spears)就会相对简单。

如果某个查询有可能有多个起点,并且Cyher的查询执行计划由于不知道超级节点的存在而错误地提供低效的执行计划,我们可以在查询中使用联接提示来防止遍历某个节点。

这时,遍历将使用多个起点、并且从每个扩展执行一次,直到到达连接提示中指定的节点为止。然后使用连接从两个方向查找匹配的公共节点,并完成匹配的路径。

如果我想找出我的朋友和我共同喜欢的艺术家(以及共同喜欢多少个艺术家),简单的查询是这样的:

MATCH (me:Person {name:'Me'})-[:FRIENDS_WITH]-(friend)-[:LIKES]->(a:Artist)<-[:LIKES]-(me)
RETURN a, count(a) as likesInCommon

如果查询计划决定仅对该查询使用一个起始点,并且没有意识到潜在的超级节点问题,则有可能选择通过:Artist节点来开始,这可能会非常昂贵:

image

 

由于Cypher查询计划可以自动重新排列相邻MATCH模式的顺序(以及某些WITH子句),因此仅对上面模式匹配进行重新排序是不能保证所要达到的目的的。 我可以使用连接提示来确保仅遍历到有问题的节点,而不遍历或从该节点出发。请注意下例中的USING JOIN ON a:

MATCH (me:Person {name:'Me'})-[:FRIENDS_WITH]-(friend)-[:LIKES]->(a:Artist)<-[:LIKES]-(me)
USING JOIN on a
RETURN a, count(a) as likesInCommon

再次查看查询计划,我们可以看到,从同一起点开始,我们沿两个不同的路径朝节点a方向移动,但没有穿过它,最终执行节点哈希连接以合并公共艺术家节点上的路径。

image

有兴趣的朋友不妨试试。

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值