NebulaGraph v3.3.0 性能报告,Match count QPS 有 2~8 倍提升,3 跳查询 QPS 时延低至原 1/3

2022-11-30 10:51:11 浏览数 (1)

NebulaGraph v3.3.0 社区版性能报告NebulaGraph v3.3.0 社区版性能报告

摘要

v3.3.0 版本主要优化了执行计划和属性裁剪,并对深度多跳场景进行特别优化,相关 case 的性能有明显的提升,相比 v3.2.0:

代码语言:txt复制
1)  Match count QPS 增幅明显,有 2~8 倍的提升;时延降低至原 1/5.
代码语言:txt复制
2) 3 跳查询 QPS 提升约 40-100%,时延低至原 1/3;
代码语言:txt复制
3) 对于内存占用和释放进行了优化
代码语言:txt复制
4) 其他各 case 有不同程度提升;

测试环境

服务器和压测机皆为物理机

测试环境测试环境

测试数据

测试数据采用 LDBC-SNB SF100 数据集,SF100 数据集大小为 100G,共有 282,386,021 个点以及 1,775,513,185 条边。测试用的图空间分区数为 24,副本数为 3。

关于 LDBC-SNB

关联数据基准委员会(LDBC,Linked Data Benchmark Council),是图(Graph)和 RDF 数据管理的基准指南制定者。社交网路基准(SNB,Social Network Benchmark)是关联数据基准委员会(LDBC)开发的软件基准(Benchmark)之一。关于 LDBC-SNB 数据集,具体请参考以下文档:

  • LDBC-SNB Specification
  • LDBC-SNB DOCs
  • LDBC-SNB 测试数据集生产工具

Nebula Commit

  • nebula-graphd version c9f84b1
  • nebula-storaged version c9f84b1
  • nebula-metad version c9f84b1

测试说明

压测工具使用基于 Go 语言的 k6,具体请参阅 k6 官方网站;客户端使用的是 nebula-go

图表中横坐标轴的 “50_vu“、“100_vu“等中的”vu“表示的是 k6 使用的概念“virtual user”,即性能测试中的并发数;50_vu 表示 50 个并发用户,100_vu 表示 100 个并发用户,以此类推…

性能基线使用正式发布的 3.2.0 版本

ResponseTime = Latency(服务端处理时长) 网络回传结果时长 客户端反序列化结果时长

基线测试

注:下图涉及的词语解释

  • QPS 即吞吐率
  • Latency 即服务端耗时
  • ResponseTime 即客户端耗时
  • RowSize 即请求返回行数

用例和结果

查询带边属性

GO {} STEP FROM {} OVER KNOWS yield KNOWS.creationDate

一跳·吞吐率

用例和结果用例和结果

一跳·服务端耗时(ms)

用例和结果用例和结果

一跳·客户端耗时(ms)

一跳·请求返回行数

用例和结果用例和结果

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·服务端耗时二跳·服务端耗时

二跳·客户端耗时(ms)

二跳·请求返回行数

二跳·请求返回行数二跳·请求返回行数

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·服务端耗时三跳·服务端耗时

三跳·客户端耗时(ms)

三跳·请求返回行数

三跳·请求返回行数三跳·请求返回行数
查询带目的点属性

GO {} STEP FROM {} OVER KNOWS yield $$.Person.firstName

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·服务端耗时一跳·服务端耗时

一跳·客户端耗时(ms)

一跳·请求返回行数

一跳·请求返回行数一跳·请求返回行数

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·服务端耗时二跳·服务端耗时

二跳·客户端耗时(ms)

二跳·请求返回行数

二跳·请求返回行数二跳·请求返回行数

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·服务端耗时三跳·服务端耗时

三跳·客户端耗时(ms)

三跳·请求返回行数

三跳·请求返回行数三跳·请求返回行数
查询带边属性 目的点属性
代码语言:txt复制
GO {} STEP FROM {} OVER KNOWS yield DISTINCT KNOWS.creationDate as t, $$.Person.firstName, $$.Person.lastName, $$.Person.birthday as birth | order by $-.t, $-.birth | limit 10

一跳·吞吐率

一跳·服务端耗时(ms)

一跳·服务端耗时一跳·服务端耗时

一跳·客户端耗时(ms)

一跳·请求返回行数

一跳·请求返回行数一跳·请求返回行数

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·服务端耗时二跳·服务端耗时

二跳·客户端耗时(ms)

二跳·请求返回行数

二跳·请求返回行数二跳·请求返回行数

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·服务端耗时三跳·服务端耗时

三跳·客户端耗时(ms)

三跳·请求返回行数

三跳·请求返回行数三跳·请求返回行数
LOOKUP

LOOKUP ON Person WHERE Person.firstName == '{}' YIELD Person.firstName, Person.lastName, Person.gender, Person.birthday, Person.creationDate, Person.locationIP, Person.browserUsed

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
FETCH 点

FETCH PROP ON Person {} YIELD Person.firstName, Person.lastName, Person.gender, Person.birthday, Person.creationDate, Person.locationIP, Person.browserUsed

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
FETCH 边

FETCH PROP ON KNOWS {} -> {} YIELD KNOWS.creationDate

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
MATCH 索引

MATCH (v:Person) WHERE v.Person.firstName == '{}' RETURN v

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
MATCH 一跳

MATCH (v1:Person)-[e:KNOWS]->(v2:Person) WHERE id(v1) == {} RETURN v2

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

![

客户端耗时](https://www-cdn.nebula-graph.com.cn/nebula-website-5.0/images/blogs/3.3.0 benchmark report/metrics/Match1Hop ResponseTime (ms) .png)

请求返回行数

请求返回行数请求返回行数
MATCH 两跳

MATCH (v1:Person)-e:KNOWS*2->(v2:Person) WHERE id(v1) == {} RETURN v2

吞吐率

吞吐率吞吐率

服务端耗时(ms)

https://www-cdn.nebula-graph.com.cn/nebula-website-5.0/images/blogs/3.3.0 benchmark report/metrics/Match2Hop Latency.png

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
插入点

INSERT VERTEXComment(creationDate, locationIP, browserUsed, content, length) VALUES {}:('{}', '{}', '{}', '{}', {})

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
插入边

INSERT EDGE LIKES (creationDate) VALUES {}→{}:('{}')

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

MatchTest1

match (v:Person) where id(v) == {} return count(v.Person.firstName)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
MatchTest2

match (v:Person)-[e:KNOWS]-(v2) where id(v) == {} and v2.Person.locationIP != 'yyy' return length(v.Person.browserUsed) length(v2.Person.gender)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

客户端耗时客户端耗时

请求返回行数

MatchTest3

match (v:Person)-[e:KNOWS]-(v2) where id(v) == {} and v2.Person.locationIP != 'yyy' with v, v2 as v3 return length(v.Person.browserUsed) (v3.Person.gender)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
MatchTest4

MATCH (m)-[:KNOWS]-(n) WHERE id(m)=={} OPTIONAL MATCH (n)<-[:KNOWS]-(l) RETURN length(m.Person.lastName) AS n1, length(n.Person.lastName) AS n2, l.Person.creationDate AS n3 ORDER BY n1, n2, n3 LIMIT 10

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
MatchTest5

MATCH (m)-[:KNOWS]-(n) WHERE id(m)=={} MATCH (n)-[:KNOWS]-(l) WITH m AS x, n AS y, l RETURN x.Person.firstName AS n1, y.Person.firstName AS n2, CASE WHEN l.Person.firstName is not null THEN l.Person.firstName WHEN l.Person.gender is not null THEN l.Person.birthday ELSE 'null' END AS n3 ORDER BY n1, n2, n3 LIMIT 10

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
查询带边属性_count

GO {} STEP FROM {} OVER KNOWS yield KNOWS.creationDate | return count(*)

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·服务端耗时一跳·服务端耗时

一跳·客户端耗时(ms)

一跳·请求返回行数

一跳·请求返回行数一跳·请求返回行数

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·服务端耗时二跳·服务端耗时

二跳·客户端耗时(ms)

二跳·请求返回行数

二跳·请求返回行数二跳·请求返回行数

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·服务端耗时三跳·服务端耗时

三跳·客户端耗时(ms)

三跳·请求返回行数

三跳·请求返回行数三跳·请求返回行数
查询带目的点属性_count

GO 1 STEP FROM {} OVER KNOWS yield $$.Person.firstName | return count(*)

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·服务端耗时一跳·服务端耗时

一跳·客户端耗时(ms)

一跳·请求返回行数

一跳·请求返回行数一跳·请求返回行数

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·服务端耗时二跳·服务端耗时

二跳·客户端耗时(ms)

二跳·请求返回行数

二跳·请求返回行数二跳·请求返回行数

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·服务端耗时三跳·服务端耗时

三跳·客户端耗时(ms)

三跳·请求返回行数

三跳·请求返回行数三跳·请求返回行数
LOOKUP_count

LOOKUP ON Person WHERE Person.firstName == '{}' YIELD Person.firstName | count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
Match_count

MATCH (v:Person) WHERE v.Person.firstName == '{}' RETURN count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
Match1Hop_count

MATCH (v1:Person)-[e:KNOWS]->(v2:Person) WHERE id(v1) == {} RETURN count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

https://www-cdn.nebula-graph.com.cn/nebula-website-5.0/images/blogs/3.3.0 benchmark report/metrics/Match1HOP_count ResponseTime (ms) .png

请求返回行数

请求返回行数请求返回行数
Match2Hop_count

MATCH (v1:Person)-[e:KNOWS*2]->(v2:Person) WHERE id(v1) == {} RETURN count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数

3.3.0 vs 3.2.0(Baseline)

以下数据选取 P99 值。

查询带边属性

GO {} STEP FROM {} OVER KNOWS yield KNOWS.creationDate

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·客户端耗时(ms)

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·客户端耗时(ms)

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·客户端耗时(ms)

查询带目的点属性

GO {} STEP FROM {} OVER KNOWS yield $$.Person.firstName

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·客户端耗时(ms)

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·客户端耗时(ms)

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·客户端耗时(ms)

查询带边属性 目的点属性

GO {} STEP FROM {} OVER KNOWS yield DISTINCT KNOWS.creationDate as t, $$.Person.firstName, $$.Person.lastName, $$.Person.birthday as birth | order by $-.t, $-.birth | limit 10

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·客户端耗时(ms)

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·客户端耗时(ms)

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·客户端耗时(ms)

LOOKUP

LOOKUP ON Person WHERE Person.firstName == '{}' YIELD Person.firstName, Person.lastName, Person.gender, Person.birthday, Person.creationDate, Person.locationIP, Person.browserUsed

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

FETCH 点

FETCH PROP ON Person {} YIELD Person.firstName, Person.lastName, Person.gender, Person.birthday, Person.creationDate, Person.locationIP, Person.browserUsed

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

FETCH 边

FETCH PROP ON KNOWS {} -> {} YIELD KNOWS.creationDate

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MATCH 索引

MATCH (v:Person) WHERE v.Person.firstName == '{}' RETURN v

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MATCH 一跳

MATCH (v1:Person)-[e:KNOWS]->(v2:Person) WHERE id(v1) == {} RETURN v2

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·客户端耗时(ms)

MATCH 两跳

MATCH (v1:Person)-[e:KNOWS*2]->(v2:Person) WHERE id(v1) == {} RETURN v2

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

插入点

INSERT VERTEXComment(creationDate, locationIP, browserUsed, content, length) VALUES {}:('{}', '{}', '{}', '{}', {})

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

插入边

INSERT EDGE LIKES (creationDate) VALUES {}→{}:('{}')

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MatchTest1

match (v:Person) where id(v) == {} return count(v.Person.firstName)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MatchTest2

match (v:Person)-[e:KNOWS]-(v2) where id(v) == {} and v2.Person.locationIP != 'yyy' return length(v.Person.browserUsed) length(v2.Person.gender)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MatchTest3

match (v:Person)-[e:KNOWS]-(v2) where id(v) == {} and v2.Person.locationIP != 'yyy' with v, v2 as v3 return length(v.Person.browserUsed) (v3.Person.gender)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MatchTest4

MATCH (m)-[:KNOWS]-(n) WHERE id(m)=={} OPTIONAL MATCH (n)<-[:KNOWS]-(l) RETURN length(m.Person.lastName) AS n1, length(n.Person.lastName) AS n2, l.Person.creationDate AS n3 ORDER BY n1, n2, n3 LIMIT 10

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

MatchTest5

MATCH (m)-[:KNOWS]-(n) WHERE id(m)=={} MATCH (n)-[:KNOWS]-(l) WITH m AS x, n AS y, l RETURN x.Person.firstName AS n1, y.Person.firstName AS n2, CASE WHEN l.Person.firstName is not null THEN l.Person.firstName WHEN l.Person.gender is not null THEN l.Person.birthday ELSE 'null' END AS n3 ORDER BY n1, n2, n3 LIMIT 10

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

查询带边属性_count

GO {} STEP FROM {} OVER KNOWS yield KNOWS.creationDate | return count(*) ;

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

查询带目的点属性_count

GO 1 STEP FROM {} OVER KNOWS yield $$.Person.firstName | return count(*)

一跳·吞吐率

一跳·吞吐率一跳·吞吐率

一跳·服务端耗时(ms)

一跳·客户端耗时(ms)

二跳·吞吐率

二跳·吞吐率二跳·吞吐率

二跳·服务端耗时(ms)

二跳·客户端耗时(ms)

三跳·吞吐率

三跳·吞吐率三跳·吞吐率

三跳·服务端耗时(ms)

三跳·客户端耗时(ms)

LOOKUP_count

LOOKUP ON Person WHERE Person.firstName == '{}' YIELD Person.firstName | count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

Match_count

MATCH (v:Person) WHERE v.Person.firstName == '{}' RETURN count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

Match1Hop_count

MATCH (v1:Person)-[e:KNOWS]->(v2:Person) WHERE id(v1) == {} RETURN count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

Match2Hop_count

MATCH (v1:Person)-[e:KNOWS*2]->(v2:Person) WHERE id(v1) == {} RETURN count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

新增测试用例-LDBC GO 属性过滤深度优化

测试用例和结果

Go3StepDistinctDst

GO 3 STEP FROM {0} OVER KNOWS REVERSELY YIELD DISTINCT KNOWS._dst as dst | YIELD count(*);

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

客户端耗时客户端耗时
Go3StepDistinctDstProp

GO 3 STEP FROM {0} OVER KNOWS WHERE $$.Person.firstName == "{1}" YIELD distinct id($$) , $$.Person.locationIP | yield count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

服务端耗时服务端耗时

客户端耗时(ms)

3.3.0 vs 3.2.0

以下数据选取 P99 值。

Go3StepDistinctDst

GO 3 STEP FROM {0} OVER KNOWS REVERSELY YIELD DISTINCT KNOWS._dst as dst | YIELD count(*);

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数
Go3StepDistinctDstProp

GO 3 STEP FROM {0} OVER KNOWS WHERE $$.Person.firstName == "{1}" YIELD distinct id($$) , $$.Person.locationIP | yield count(*)

吞吐率

吞吐率吞吐率

服务端耗时(ms)

客户端耗时(ms)

请求返回行数

请求返回行数请求返回行数

  • NebulaGraph 的开源地址:https://github.com/vesoft-inc/nebula 觉得使用体验还不错的话,给我们的 GitHub 点个 ❤️ 鼓励下开源路上的我们呢~

0 人点赞