nebulaGraph 性能优化问题

  • 机器数:单节点
  • 内存:32G
  • 硬盘:200G
  • cpu核数:8
  • nebulaGraph: 3.6.0

请问这个配置能支持大概多少定点和边?

目前正在测试 nebulaGraph 性能,看是否适合当前业务。我在以上配置中部署了一个3.6.0版本单节点nebulaGraph,有366万定点,其中person标签下节点160万,job标签下节点160万,3390万边。跑

match (c:person)-[r1:tend_city]->(i:city) where i.city.name=="深圳" with c 
match (c:person)-[r1:have_skill]->(s:skill) where s.skill.name =="Java" with c 
match (c:person)-[r1:have_gackground]->(e:education_background) where e.education_background.name == "本科" with c 
match (c:person)-[r1:study_major]->(m:major) where m.major.name in ["计算机科学","软件工程"] with c match (c:person)-[r1:have_degree]->(d:degree) where d.degree.name in ["学士","硕士"] 
return c.person.name as person;

需要 4.3 秒,跑 match (c:person)-[]-(n)-[]-(p:job{name:"高级Java开发工程师"}) return c.person.name,count(n) as cnt order by cnt desc limit 5;需要 73 秒,

请问这个还能优化吗?

你可以在这两个语句前面加上 profile,看下对应的执行计划到底哪里比较耗时。





谢谢,以上是执行计划,我标出了比较耗时的点,请问如何进行分析和优化呢?

你可以直接把执行计划全部贴过来么。:thinking: 截图不是很完整,有些信息丢了。

好的,这是顶点数500多万,边数4000万,profile match (c:person)--(n)--(p:job{name:“高级Java开发工程师”}) return c.person.name,count(n) as cnt order by cnt desc limit 5;的执行计划。
result.csv (25.9 KB)

其实你看执行计划能看到 traverse 这个算子(AppendVertices 耗时也很长,不过它是搭配 traverse
来的),其实耗时很久,后面输出有非常多的 tag 捞取数据,和你的语句里没有指明点类型(tag)以及边(edgetype)有关系

match (c:person)-[]-(n)-[]-(p:job{name:"高级Java开发工程师"}) return c.person.name,count(n) as cnt order by cnt desc limit 5
  • (c:person):指明了 person tag,避免捞所有的 tag 信息;
  • []:没有指明任何一个边类型(edgetype),只能捞所有数据,下面的 n[]、同这块信息;

反之可以对比的是你 4.3 的语句,每个表达式中都有明确的类型,有些甚至都指明了特定的属性,这样执行的时候可能属性裁剪的功能能起作用,节省时间。

以及,你的执行计划只有一台 storage 数据的信息,如果数据落盘都在一个机器的话,那就只能去一台机器上捞数据可能比去多台机器上捞数据要慢。

结论就是。。你如果要优化这个语句话的,可以加一点过筛的条件,指明 tag 类型或者 edgetype。

从这个props,看上去属性裁剪已经正常生效了。

 "props": [
      "_dst",
      "_type",
      "_rank"
    ],

您这边
match (c:person)-[]-(n)-[]-(p:job{name:"高级Java开发工程师"})边和点的类型都没有限制,观察profile也能看到中间结果是非常大的。我想这个时间消耗是符合预期的。

1 个赞

由于业务中其他的tag和edgetype都是person和job这两个tag的关联点和边,因此中间的-(n)-包含了剩余的所有tag和edgetype,以下是我指定了edgetype后的语句和执行计划,还是很慢

profile match (c:person)-[:except_post|have_degree|have_gackground|have_manage_experience|have_skill|study_course|study_major|tend_city]-(n)-[:provide_post|require_course|require_degree|require_education_background|require_major|require_manage_experience|require_skill|require_work_city]-(p:job{name:"高级Java开发工程师"}) return c.person.name,count(n) as cnt order by cnt desc limit 5;

result.csv (7.8 KB)

由于业务中其他的tag和edgetype都是person和job这两个tag的关联点和边,因此中间的-(n)-包含了剩余的所有tag和edgetype,以下是我指定了edgetype后的语句和执行计划,还是很慢
profile match (c:person)-[:except_post|have_degree|have_gackground|have_manage_experience|have_skill|study_course|study_major|tend_city]-(n)-[:provide_post|require_course|require_degree|require_education_background|require_major|require_manage_experience|require_skill|require_work_city]-(p:job{name:“高级Java开发工程师”}) return c.person.name,count(n) as cnt order by cnt desc limit 5;
result.csv (7.8 KB)

嗯嗯,这个结果应该是符合预期的。可以看到"rows": 7003343中间的结果集是很大的。

你把所有的边类型(盲猜的,我不确定你的 except_post|have_degree|have_gackground|have_manage_experience|have_skill|study_course|study_major|tend_city 是不是所有边类型)都加上手其实和不加边类型的效果是一样的。

是的,从业务上来看,是需要对所有边进行关联的,这种场景的话有什么好的解决办法吗

:thinking: 蹲个大佬回复,反正我觉得是没有啥可优化空间了。

有几个建议:

  1. 应该把 city 的深圳做为 vid,skill 的 name 的 java 做为 vid,background 的 name ,major 的 name 都做为 vid,通过 vid 查询效率会高很多
    2.第二个的查询应该是有向的?建议把边的方向加上。
  2. 第一条语句你改成:
    match (c:person)-[r1:tend_city]->(i:city) where id(i) ==“深圳” match (c:person)-[r1:have_skill]->(s:skill) where id(s)=“Java” match (c:person)-[r1:have_gackground]->(e:education_background) where id(e) == “本科” match (c:person)-[r1:study_major]->(m:major) where id(m) in [“计算机科学”,“软件工程”] match (c:person)-[r1:have_degree]->(d:degree) where id(d) in [“学士”,“硕士”] return c.person.name as person;
  3. 第二条语句的 count 是 count 啥?
1 个赞

另外一个,也可以考虑把 city/background 等做为person点的属性来做;
当然这种方式就不是纯粹的图的用法了

谢谢,对,第二条语句是有向的,但是加上了有向后效果也不明显,count是想统计person和job连接到共同的顶点的个数

对,对于第一条语句通过查询person的带索引的属性速度会快很多

可以考虑下:

  1. 把 job 做为 vid
  2. 用 FIND noloop path,然后判断长度 = 2,再group by,order by, limit


您好,如图我尝试了一下,我想group by 结束节点,这个group by 语法怎么写呢

find path 不支持 group by 操作,它倒是支持 order by,但是 order by 是根据你第一步出去的终点排序的,而不是最后一步的终点排序。:thinking: 你可以用 match 来换下表达。