查询语句写了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,进一步提升语句执行速度。
总结
通过这次分析也可以看出,很多时候计算引擎会对语句进行代价估计并调整语句的执行顺序。执行计划是语句如何执行的直观表达。语句如何执行不能只关注语句写法,要想写出符合预期执行顺序的查询语句,还需要关注语句执行计划。
查询语句写了limit 1,为什么依然很慢?的更多相关文章
- mysql查询语句,通过limit来限制查询的行数。
mysql查询语句,通过limit来限制查询的行数. 例如: select name from usertb where age > 20 limit 0, 1; //限制从第一条开始,显示1条 ...
- SQL查询语句中的 limit offset(转 )
经常用到在数据库中查询中间几条数据的需求 比如下面的sql语句: ① selete * from testtable limit 2,1; ② selete * from testtable limi ...
- sql查询语句如何解析成分页查询?
我们公司主要mysql存储数据,因此也封装了比较好用mysql通用方法,然后,我们做大量接口,在处理分页查询接口,没有很好分查询方法.sql查询 语句如何解析成“分页查询”和“总统计”两条语句.可能, ...
- Mysql查询语句的 where子句、group by子句、having子句、order by子句、limit子句
Mysql的各个查询语句 一.where子句 语法:select *|字段列表 from 表名 where 表达式.where子句后面往往配合MySQL运算符一起使用(做条件判断) 作用:通过限定 ...
- NumberFormatException: Invalid int类型不匹配异常——使用SQL数据库查询语句select * from blacknumber order by _id desc limit ?,20;出现
异常:类型不匹配 05-06 08:12:38.151: E/AndroidRuntime(14904): java.lang.NumberFormatException: Invalid int: ...
- Hibernate三种状态;query查询;ResultTransformer转换为pojo对象;能够将query语句写在xml中;Criteria查询;ProjectionList总和/f分组等函数
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010026901/article/details/24256091 Session操作过程中的po ...
- MySQL知识树-查询语句
在日常的web应用开发过程中,一般会涉及到数据库方面的操作,其中查询又是占绝大部分的.我们不仅要会写查询,最好能系统的学习下与查询相关的知识点,这篇随笔我们就来一起看看MySQL查询知识相关的树是什么 ...
- MYSQL查询语句优化
mysql的性能优化包罗甚广: 索引优化,查询优化,查询缓存,服务器设置优化,操作系统和硬件优化,应用层面优化(web服务器,缓存)等等.这里的记录的优化技巧更适用于开发人员,都是从网络上收集和自己整 ...
- php面试专题---MYSQL查询语句优化
php面试专题---MYSQL查询语句优化 一.总结 一句话总结: mysql的性能优化包罗甚广: 索引优化,查询优化,查询缓存,服务器设置优化,操作系统和硬件优化,应用层面优化(web服务器,缓存) ...
随机推荐
- 从ES6重新认识JavaScript设计模式(三): 建造者模式
1 什么是建造者模式? 建造者模式(Builder)是将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示. 建造者模式的特点是分步构建一个复杂的对象,可以用不同组合或顺序建造出不 ...
- 【Android开发】Android工程打压缩包技巧
android studio的: ".gradle" "*/.gradle" ".idea" "*/.idea" &qu ...
- 世界各国 MCC 和 MNC 列表
http://www.cnblogs.com/inteliot/archive/2012/08/22/2651666.html常见MCC:代码(MCC) ISO 3166-1 国家202 ...
- 一个chome的广告拦截小插件
先附上下载地址:https://chromecj.com/productivity/2015-03/391.html 可以屏蔽绝大多数广告啊,浏览器用起来神清气爽! 下载完成后有一个名字为这个的文件, ...
- hibernate数据源
Hibernate的描述文件可以是一个properties属性文件,也可以是一个xml文件.下面讲一下Hibernate.cfg.xml的配置.配置格式如下:1. 配置数据源 在Hibernate ...
- 前端加密办法之混淆js加密
每个页面都是有数据和页面结构以及样式组成,对于单页面的作者来说这中分离的感觉会明显一点,那当我们通过ajax请求拿到数据之后我们一般就是把数据渲染到页面,但是数据接口又不想那么明显是一个json字符串 ...
- Python入门-import导入模块功能
1.啥是模块 模块(module):用来实现或者多个功能的Python代码,(包含变量.函数.类),本质就是*.py后缀文件. 包(package):定义了一个由模块和子包组成的Python应用程序执 ...
- cannot find module providing package github.com/× working directory is not part of a module
今天在搭建fabric的过程中遇到一个问题,记录一下 root@zitao /home/hong/Desktop/gowork/src/github.com/hyperledger/fabric re ...
- crm多对多
多对多要使用service.Associate传入两表的id和中间表的 service.Associate("invoice", entityReferenceInvoice.Id ...
- Python Json分别存入Mysql、MongoDB数据库,使用Xlwings库转成Excel表格
将电影数据 data.json 数据通过xlwings库转换成excel表格,存入mysql,mongodb数据库中.python基础语法.xlwings库.mysql库.pymongo库.mongo ...