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


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

    本文分享自华为云社区《查询语句写了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,进一步提升语句执行速度。

    总结

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

     

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

  • 相关阅读:
    break-continue
    函数定义
    函数类型
    为何要继承SpringBootServletInitializer,为何要实现configure这方法
    查询一个表中的两个字段值相同的数据
    数据库中查出来的时间多8小时&查询数据正常展示少8小时
    @JsonFormat与@DateTimeFormat注解的使用
    用js获取当前月份的天数
    js获取当前年,月,日,时,分,秒
    maven配置和安装
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/16329393.html
Copyright © 2020-2023  润新知