写点什么

查询语句写了 limit 1,为什么依然很慢?

  • 2022 年 5 月 31 日
  • 本文字数:1442 字

    阅读完需:约 5 分钟

本文分享自华为云社区《查询语句写了limit 1,为什么依然很慢? 记一次图引擎GES cypher慢查询的定位分析》,作者: 蜉蝣与海。

问题背景


最近使用华为图引擎 GES, 有一条 cypher 语句携带后缀 limit 1,理论上应该很快返回结果,可是跑了很久依旧没有返回,简化后的语句如下:

match(v)-[r1:dependency *1..1]->(node) where node.product_name = "product" match path = (m)-[r:dependency*0..10]-> (v:Material) return path, m,node skip 0 limit 10复制
复制代码


调整 limit 10 至 limit 1,结果依旧很慢。


华为云图引擎GES官网文档上,发现了对查询语句进行终止的接口:


首先使用 listQueries 查询出当前 cypher 语句的 queryId,然后把 queryId 输入 killQuery 中终止慢查询。

问题分析:为什么 limit 配置为 1,依旧长时间无结果?


在华为云图引擎控制台,使用 explain 打印 cypher 查询计划,分析慢查询生成原因,简化后的查询计划如图:


可以看到,查询语句的执行和预期有差异。查询语句优先执行了一个 Label 扫描算子(NodeByLabelScan),对扫描到的每个点按入边方向进行了[r*0..10]这样的 10 跳操作,而后再从出边方向做了一跳并过滤,这就导致了最坏情况下,需要全图 Label 为 Material 的点都跳完 10 跳,才能拿到一条结果。如上图表格所示,在遍历到第一个满足条件的(vi)之前,已经对(v0)到(vi)这些点都做了 10 跳。即使语句末尾写了 limit 1,因为始终遍历不到合适的数据,导致了后台的计算引擎一直在做计算。


估计计算引擎在读取这条语句时,同时看到了 v:Material 和 node.product='xxx'两个过滤条件,而代价估计模型认为 v:Material 可以获得更低的代价,所以才选择优先执行 NodeByLabelScan。

使用语句优化策略对语句进行优化


既然分析清楚了原因,那么只要通过改写 cypher 语句,让 GES 的 cypher 不优先通过 v:Material 做计划即可。这里用到下列两类策略:


with 别名策略:使用 with 为变量安排别名,强制规定语句不同子句的执行顺序


label 过滤改写策略:将 label 过滤条件放在 where 语句中,并使用 labels 函数,防止生成 NodeByLabelScan 的计划


使用 with 别名策略后,语句如下:

match(v0)-[r1:dependency *1..1]->(node) where node.product_name = "product" with v0 as v,node match path = (m)-[r:dependency*0..10]-> (v:Material) return path, m,node skip 0 limit 10复制
复制代码


使用 label 过滤改写策略,语句如下:

match(v)-[r1:dependency *1..1]->(node) where node.product_name = "product" match path = (m)-[r:dependency*0..10]-> (v) where labels(v)='Material' return path, m,node skip 0 limit 10复制
复制代码


两种策略混合使用,语句如下:

match(v0)-[r1:dependency *1..1]->(node) where node.product_name = "product" with v0 as v,node match path = (m)-[r:dependency*0..10]-> (v) where labels(v)= " Material" return path, m,node skip 0 limit 10复制
复制代码


使用 explain 将三种查询计划分别打印,如图:


可以看到 with 别名更有效,生成的计划更符合期望。


使用 with 别名策略改写 cypher 语句后,语句运行时间从 130 秒降到 3 秒。语句中依旧存在 AllNodesScan 算子,而华为图引擎 GES 是支持索引能力的,后续会考虑加入合适的索引,把 AllNodesScan 和 Filter 优化为 NodeIndexSeek,进一步提升语句执行速度。

总结


通过这次分析也可以看出,很多时候计算引擎会对语句进行代价估计并调整语句的执行顺序。执行计划是语句如何执行的直观表达。语句如何执行不能只关注语句写法,要想写出符合预期执行顺序的查询语句,还需要关注语句执行计划。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
查询语句写了limit 1,为什么依然很慢?_后端_华为云开发者社区_InfoQ写作社区