关于图数据库:主流开源分布式图数据库-Benchmark

46次阅读

共计 6001 个字符,预计需要花费 16 分钟才能阅读完成。

本文由美团 NLP 团队高辰、赵登昌撰写
首发于 Nebula Graph 官方论坛:https://discuss.nebula-graph.com.cn/t/topic/1377

1. 前言

近年来,深度学习和常识图谱技术倒退迅速,相比于深度学习的“黑盒子”,常识图谱具备很强的可解释性,在搜寻举荐、智能助理、金融风控等场景中有着宽泛的利用。美团基于积攒的海量业务数据,联合应用场景进行充沛地开掘关联,逐渐建设起包含美食图谱、游览图谱、商品图谱在内的近十个畛域常识图谱,并在多业务场景落地,助力本地生存服务的智能化。

为了高效存储并检索图谱数据,相比传统关系型数据库,抉择图数据库作为存储引擎,在多跳查问上具备显著的性能劣势。以后业界出名的图数据库产品有数十款,选型一款可能满足美团理论业务需要的图数据库产品,是建设图存储和图学习平台的根底。咱们联合业务现状,制订了选型的根本条件:

  • 开源我的项目,对商业利用敌对

    • 领有对源代码的控制力,能力保障数据安全和服务可用性。
  • 反对集群模式,具备存储和计算的横向扩大能力

    • 美团图谱业务数据量能够达到千亿以上点边总数,吞吐量可达到数万 qps,单节点部署无奈满足存储需要。
  • 可能服务 OLTP 场景,具备毫秒级多跳查问能力

    • 美团搜寻场景下,为确保用户搜寻体验,各链路的超时工夫具备严格限度,不能承受秒级以上的查问响应工夫。
  • 具备批量导入数据能力

    • 图谱数据个别存储在 Hive 等数据仓库中。必须有疾速将数据导入到图存储的伎俩,服务的时效性能力失去保障。

咱们试用了 DB-Engines 网站上排名前 30 的图数据库产品,发现少数出名的图数据库开源版本只反对单节点,不能横向扩大存储,无奈满足大规模图谱数据的存储需要,例如:Neo4j、ArangoDB、Virtuoso、TigerGraph、RedisGraph。通过调研比拟,最终纳入评测范畴的产品为:NebulaGraph(原阿里巴巴团队守业开发)、Dgraph(原 Google 团队守业开发)、HugeGraph(百度团队开发)。

2. 测试概要

2.1 硬件配置

  • 数据库实例:运行在不同物理机上的 Docker 容器。
  • 单实例资源:32 外围,64GB 内存,1TB SSD 存储。【Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz】
  • 实例数量:3

2.2 部署计划

  • Nebula v1.0.1

Metad 负责管理集群元数据,Graphd 负责执行查问,Storaged 负责数据分片存储。存储后端采纳 RocksDB。

实例 1 实例 2 实例 3
Metad Metad Metad
Graphd Graphd Graphd
Storaged[RocksDB] Storaged[RocksDB] Storaged[RocksDB]
  • Dgraph v20.07.0

Zero 负责管理集群元数据,Alpha 负责执行查问和存储。存储后端为 Dgraph 自有实现。

实例 1 实例 2 实例 3
Zero Zero Zero
Alpha Alpha Alpha
  • HugeGraph v0.10.4

HugeServer 负责管理集群元数据和查问。HugeGraph 尽管反对 RocksDB 后端,但不反对 RocksDB 后端的集群部署,因而存储后端采纳 HBase。

实例 1 实例 2 实例 3
HugeServer[HBase] HugeServer[HBase] HugeServer[HBase]
JournalNode JournalNode JournalNode
DataNode DataNode DataNode
NodeManager NodeManager NodeManager
RegionServer RegionServer RegionServer
ZooKeeper ZooKeeper ZooKeeper
NameNode NameNode[Backup]
ResourceManager ResourceManager[Backup]
HBase Master HBase Master[Backup]

3. 评测数据集

  • 社交图谱数据集:https://github.com/ldbc011

    • 生成参数:branch=stable, version=0.3.3, scale=1000
    • 实体状况:4 类实体,总数 26 亿
    • 关系状况:19 类关系,总数 177 亿
    • 数据格式:csv
    • GZip 压缩后大小:194 G

4. 测试后果

4.1 批量数据导入

4.1.1 测试阐明

批量导入的步骤为:Hive 仓库底层 csv 文件 -> 图数据库反对的两头文件 -> 图数据库。各图数据库具体导入形式如下:

  • Nebula:执行 Spark 工作,从数仓生成 RocksDB 的底层存储 sst 文件,而后执行 sst Ingest 操作插入数据。
  • Dgraph:执行 Spark 工作,从数仓生成三元组 rdf 文件,而后执行 bulk load 操作间接生成各节点的长久化文件。
  • HugeGraph:反对间接从数仓的 csv 文件导入数据,因而不须要数仓 - 两头文件的步骤。通过 loader 批量插入数据。

4.1.2 测试后果

4.1.3 数据分析

  • Nebula:数据存储散布形式是主键哈希,各节点存储散布根本平衡。导入速度最快,存储放大比最优。
  • Dgraph:原始 194G 数据在内存 392G 的机器上执行导入命令,8.7h 后 OOM 退出,无奈导入全量数据。数据存储散布形式是三元组谓词,同一种关系只能保留在一个数据节点上,导致存储和计算重大偏斜。
  • HugeGraph:原始 194G 的数据执行导入命令,写满了一个节点 1,000G 的磁盘,造成导入失败,无奈导入全量数据。存储放大比最差,同时存在重大的数据偏斜。

4.2 实时数据写入

4.2.1 测试阐明

  • 向图数据库插入点和边,测试实时写入和并发能力。

    • 响应工夫:固定的 50,000 条数据,以固定 qps 收回写申请,全副发送结束即完结。取客户端从发出请求到收到响应的 Avg、p99、p999 耗时。
    • 最大吞吐量:固定的 1,000,000 条数据,以递增 qps 收回写申请,Query 循环应用。取 1 分钟内胜利申请的峰值 qps 为最大吞吐量。
  • 插入点

    • Nebula

      INSERT VERTEX t_rich_node (creation_date, first_name, last_name, gender, birthday, location_ip, browser_used) VALUES ${mid}:('2012-07-18T01:16:17.119+0000', 'Rodrigo', 'Silva', 'female', '1984-10-11', '84.194.222.86', 'Firefox')
    • Dgraph

      {
          set {<${mid}> <creation_date> "2012-07-18T01:16:17.119+0000" .
              <${mid}> <first_name> "Rodrigo" .
              <${mid}> <last_name> "Silva" .
              <${mid}> <gender> "female" .
              <${mid}> <birthday> "1984-10-11" .
              <${mid}> <location_ip> "84.194.222.86" .
              <${mid}> <browser_used> "Firefox" .
          }
      }
    • HugeGraph

      g.addVertex(T.label, "t_rich_node", T.id, ${mid}, "creation_date", "2012-07-18T01:16:17.119+0000", "first_name", "Rodrigo", "last_name", "Silva", "gender", "female", "birthday", "1984-10-11", "location_ip", "84.194.222.86", "browser_used", "Firefox")
  • 插入边

    • Nebula

      INSERT EDGE t_edge () VALUES ${mid1}->${mid2}:();
    • Dgraph

      {
          set {<${mid1}> <link> <${mid2}> .
          }
      }
    • HugeGraph

      g.V(${mid1}).as('src').V(${mid2}).addE('t_edge').from('src')

4.2.2 测试后果

  • 实时写入

4.2.3 数据分析

  • Nebula:如 4.1.3 节剖析所述,Nebula 的写入申请能够由多个存储节点分担,因而响应工夫和吞吐量均大幅当先。
  • Dgraph:如 4.1.3 节剖析所述,同一种关系只能保留在一个数据节点上,吞吐量较差。
  • HugeGraph:因为存储后端基于 HBase,实时并发读写能力低于 RocksDB(Nebula)和 BadgerDB(Dgraph),因而性能最差。

4.3 数据查问

4.3.1 测试阐明

  • 以常见的 N 跳查问返回 ID,N 跳查问返回属性,独特好友查问申请测试图数据库的读性能。

    • 响应工夫:固定的 50,000 条查问,以固定 qps 收回读申请,全副发送结束即完结。取客户端从发出请求到收到响应的 Avg、p99、p999 耗时。

      • 60s 内未返回后果为超时。
    • 最大吞吐量:固定的 1,000,000 条查问,以递增 qps 收回读申请,Query 循环应用。取 1 分钟内胜利申请的峰值 qps 为最大吞吐量。
    • 缓存配置:参加测试的图数据库都具备读缓存机制,默认关上。每次测试前均重启服务清空缓存。
  • N 跳查问返回 ID

    • Nebula

      GO ${n} STEPS FROM ${mid} OVER person_knows_person
    • Dgraph

      {q(func:uid(${mid})) {
         uid
         person_knows_person {#${n}跳数 = 嵌套层数
           uid
         }
       }
      }
    • HugeGraph

      g.V(${mid}).out().id() #${n}跳数 = out()链长度
  • N 跳查问返回属性

    • Nebula

      GO ${n} STEPS FROM ${mid} OVER person_knows_person YIELDperson_knows_person.creation_date, $$.person.first_name, $$.person.last_name, $$.person.gender, $$.person.birthday, $$.person.location_ip, $$.person.browser_used
    • Dgraph

      {q(func:uid(${mid})) {
          uid first_name last_name gender birthday location_ip browser_used
          person_knows_person {#${n}跳数 = 嵌套层数
            uid first_name last_name gender birthday location_ip browser_used
          }
        }
      }
    • HugeGraph

      g.V(${mid}).out()  #${n}跳数 = out()链长度
  • 独特好友查问语句

    • Nebula

      GO FROM ${mid1} OVER person_knows_person INTERSECT GO FROM ${mid2} OVER person_knows_person
    • Dgraph

      {var(func: uid(${mid1})) {
          person_knows_person {M1 as uid}
        }
        var(func: uid(${mid2})) {
          person_knows_person {M2 as uid}
        }
        in_common(func: uid(M1)) @filter(uid(M2)){uid}
      }
    • HugeGraph

      g.V(${mid1}).out().id().aggregate('x').V(${mid2}).out().id().where(within('x')).dedup()

4.3.2 测试后果

  • N 跳查问返回 ID

  • N 跳查问返回属性

单个返回节点的属性均匀大小为 200 Bytes。

  • 独特好友

本项未测试最大吞吐量。

4.3.3 数据分析

  • 在 1 跳查问返回 ID「响应工夫」试验中,Nebula 和 DGraph 都只须要进行一次出边搜寻。因为 DGraph 的存储个性,雷同关系存储在单个节点,1 跳查问不须要网络通信。而 Nebula 的实体散布在多个节点中,因而在试验中 DGraph 响应工夫体现略优于 Nebula。
  • 在 1 跳查问返回 ID「最大吞吐量」试验中,DGraph 集群节点的 CPU 负载次要落在存储关系的单节点上,造成集群 CPU 利用率低下,因而最大吞吐量仅有 Nebula 的 11%。
  • 在 2 跳查问返回 ID「响应工夫」试验中,因为上述起因,DGraph 在 qps=100 时曾经靠近了集群负载能力下限,因而响应工夫大幅变慢,是 Nebula 的 3.9 倍。
  • 在 1 跳查问返回属性试验中,Nebula 因为将实体的所有属性作为一个数据结构存储在单节点上,因而只须要进行【出边总数 Y】次搜寻。而 DGraph 将实体的所有属性也视为出边,并且散布在不同节点上,须要进行【属性数量 X * 出边总数 Y】次出边搜寻,因而查问性能比 Nebula 差。多跳查问同理。
  • 在独特好友试验中,因为此试验根本等价于 2 次 1 跳查问返回 ID,因而测试后果靠近,不再详述。
  • 因为 HugeGraph 存储后端基于 HBase,实时并发读写能力低于 RocksDB(Nebula)和 BadgerDB(Dgraph),因而在多项试验中性能体现均落后于 Nebula 和 DGraph。

5. 论断

参加测试的图数据库中,Nebula 的批量导入可用性、导入速度、实时数据写入性能、数据多跳查问性能均优于竞品,因而咱们最终抉择了 Nebula 作为图存储引擎。

6. 参考资料

  • NebulaGraph Benchmark:https://discuss.nebula-graph.com.cn/t/topic/782
  • NebulaGraph Benchmark 微信团队:https://discuss.nebula-graph.com.cn/t/topic/1013
  • DGraph Benchmark:https://dgraph.io/blog/tags/benchmark/
  • HugeGraph Benchmark:https://hugegraph.github.io/hugegraph-doc/performance/hugegraph-benchmark-0.5.6.html
  • TigerGraph Benchmark:https://www.tigergraph.com/benchmark/
  • RedisGraph Benchmark:https://redislabs.com/blog/new-redisgraph-1-0-achieves-600x-faster-performance-graph-databases/

本次性能测试系美团 NLP 团队高辰、赵登昌撰写,如果你对本文有任意疑难,欢送来原贴和作者交换:https://discuss.nebula-graph.com.cn/t/topic/1377

正文完
 0