查询性能与边数量关系

nebula 版本:3.2.1
Studio版本:3.2.3
部署方式:分布式
安装方式:RPM
是否为线上版本:Y
硬件信息
磁盘 SSD
CPU、内存信息 单节点 4core8g
问题的具体描述

咨询下,两个点之间存在一条边的情况,与两个点之间存在10条边的情况,在查询性能上是不是点之间的边越多查询性能越差?还是说查询性能与两个点之间的边的数量没有直接的关系

性能和数据量肯定是有关系的,不过还要看你具体的查询语句,有些查询语句优化下可能多数据量的查询会更快(相比较没优化过的语句)

如果你想优化某个具体的场景查询的话,可以按照这个模版提交个问题哈 关于性能有调优的你应该知道的非技术姿势 或者在本帖下更新也可以~

O(nlog(n)) ?

两个 vertex 之间的多个边会有不同的 edge type,不同的 rank 等等,这些信息都是编码进了边的 key 的。也就是说两个 vertex 之间的多个边的 key 是不一样的,物理上是独立的记录。具体参考下面的代码。

那么也就是说如果你的查询本身指定了 edge type 和 rank 等信息的话,按照拼出来的很明确的 key 去做查询,此时的性能并不太会受其它边的影响。

如果你的查询没有指定这些信息的话,最终的查询实际上是在做范围扫描,那么工作量就比较多了。

对于写查询的建议就是尽可能多的写明确的 schema,明确的 predicate,包括 edge type,减少工作量,减少数据量。

std::string NebulaKeyUtils::edgeKey(size_t vIdLen,
                                    PartitionID partId,
                                    const VertexID& srcId,
                                    EdgeType type,
                                    EdgeRanking rank,
                                    const VertexID& dstId,
                                    EdgeVerPlaceHolder ev) {
  CHECK_GE(vIdLen, srcId.size());
  CHECK_GE(vIdLen, dstId.size());
  int32_t item = (partId << kPartitionOffset) | static_cast<uint32_t>(NebulaKeyType::kEdge);

  std::string key;
  key.reserve(kEdgeLen + (vIdLen << 1));
  key.append(reinterpret_cast<const char*>(&item), sizeof(PartitionID))
      .append(srcId.data(), srcId.size())
      .append(vIdLen - srcId.size(), '\0')
      .append(reinterpret_cast<const char*>(&type), sizeof(EdgeType))
      .append(NebulaKeyUtils::encodeRank(rank))
      .append(dstId.data(), dstId.size())
      .append(vIdLen - dstId.size(), '\0')
      .append(1, ev);
  return key;
}
3 个赞

感觉这个信息对我非常有用。但是我遇到建模上的一个问题,场景如下:
比如说我有两个vertex,一个A,一个B,并且A与B之间是关系比较多,为10个,针对这种情况,我是建立10个edge type呢,还是只建立一个edge type,并增加边上的一个属性进行区分呢?
希望大佬能给出一些中肯的建议,先感谢啦

一个 edge type 包含了自己这个 type 的属性,不同的 type,属性 by design 应该是差距比较大的,比如一个“朋友”关系和一个“投资”关系,两者上的属性应该会区别比较大。

建议从关系的实际含义的角度出发来定义 edge type,这样做在性能和表达能力等方面上都是比较好的,也很自然。如果相同起点终点,相同 edge type,那么可以用 rank 来区分边。

用属性作区分,一方面含义上不自然,一方面性能会比较差,因为属性没有被编码到 key 里面,它是 value 的一部分。

看下文档中关于图建模的部分吧:图建模 - NebulaGraph Database 手册

你贴的这个链接我已经详细参考过了。
另外,我补充一下我的场景: 不同关系属性完全一样。基于这样的一个限定的的话,是不是只建立一个edge type,通过rank来区分边(也可以使用rank值做过滤),通过属性来做过滤,是否比定义多种edge type类型有优势?

可以指望用 rank 做区分,rank 是编码到 key 里面的。不建议用属性,属性不在 key 里面。

多种 edge type 既通用,性能也不错,没啥劣势的。如果你不考虑关系的属性可能会变化,可能会不一样,一定要在 type 上做特化的话,用一个 type 也行。从设计上,我是不建议这么搞,这么搞扩展性比较差,也没啥好处其实,只能说跟多种 edge type 在你的特化场景上持平吧。

此话题已在最后回复的 30 天后被自动关闭。不再允许新回复。