关于超级节点 / 稠密点的处理方法

这个问题虽然在文档 超级节点(稠密点) - NebulaGraph Database 手册 有所涉及,在这里再结合下相关的帖子,汇总下相关信息。

超级节点的查找

首先要解决的是如何判断这是一个超级节点,这里涉及到如何统计某个点的出入度。

根据 如何在 Nebula Graph 中计算结点的出入度 贴中 nicole 的建议,你可以使用 nebula-algorithm 借助图计算来计算点的出入度。可以参考代码:nebula-algorithm/example/src/main/scala/com/vesoft/nebula/algorithm/DegreeStaticExample.scala at 20573b33096712a59a36447723af41c7ee068824 · vesoft-inc/nebula-algorithm · GitHub

或者根据 nGQL 的语法,比如:

# 特定点的出入度
MATCH (v1)-[e]->(v2) WHERE id(v1) == "xxx" RETURN count(e);

# 大于指定出入度的所有点
MATCH (:tag1)<-[:e]-(v:tag2)-[:e]->(:tag3)
RETURN distinct v
MATCH (v:tag1)-[:e]->(:tag2)
where size((v)-[:e]->())>2
RETURN distinct v

找寻到超级节点。

超级节点的处理

这里直接引用文档内容:

数据库端的常见办法

  1. 截断: 只访问一定阈值的边,超过该阈值的其他边则不返回。
  2. Compact:重新组织 RocksDB 中数据的排列方式,减少随机读,增加顺序读。

应用端的常见办法

根据业务意义,将一些超级顶点拆分:

  • 删除多条边,合并为一条
    例如,一个转账场景: (账户 A)-[转账]->(账户 B)。每次转账建模为一条 AB 之间的边,那么(账户 A)(账户 B)之间会有着数万十次转账的场景。按日、周、或者月为粒度,合并陈旧的转账明细。也就是批量删除陈旧的边,改为少量的边“月总额”和“次数。而保留最近月的转账明细。

  • 拆分相同类型的边,变为多种不同类型的边
    例如,(机场)<-[depart]-(航班)场景,每个架次航班的离港,都建模为一条航班和机场之间的边。那么大型机场的离港航班会极多。根据不同的航空公司depart 这个 Edge type 拆分更细的 Edge type,如 depart_ceair, depart_csair 等。在查询(图遍历)时,指定离港的航空公司。

  • 切分顶点本身
    例如,对于(人)-[借款]->(银行)的借款网络,某大型银行 A 的借款次数和借款人会非常的多。可以将该大行节点 A 拆分为多个相关联的子节点 A1、A2、A3,

     (人 1)-[借款]->(银行 A1), (人 2)-[借款]->(银行 A2), (人 2)-[借款]->(银行 A3);
     (银行 A1)-[属于]->(银行 A), (银行 A2)-[属于]->(银行 A), (银行 A3)-[属于]->(银行 A).
    

    这里的 A1、A2、A3 既可以是 A 真实的三个分行(例如北京、上海、浙江),也可以是三个按某种规则设立的虚拟分行,例如按借款金额划分 A1: 1-1000, A2: 1001-10000, A3: 10000+。这样,查询时对于 A 的任何操作,都转变为为对于 A1、A2、A3 的三次单独操作。

相关帖子

3 个赞