2. 图数据库选型:Neo4j、JanusGraph、ArangoDB 对比与选择

图数据库选型这件事,说实话没少让我头疼。早年我带团队做药物知识图谱,一开始拍脑袋选了某个库,结果查询延迟暴增,运维成本翻倍。后来被迫迁移数据,那滋味可不好受。所以这一章我结合实战经验,把几个主流图数据库掰开揉碎讲清楚。

2.1 三大主流图数据库概览

目前药物图谱场景中用得最多的,就是 Neo4j、JanusGraph 和 ArangoDB。它们各有擅长的地盘,没有银弹。

特性 Neo4j JanusGraph ArangoDB
存储引擎 本地 Native 存储 后端可插拔(HBase/Cassandra/BerkeleyDB) 自研多模型存储
查询语言 Cypher(原生属性图) Gremlin(遍历式) AQL(类 SQL + 图遍历)
分布式 企业版集群,社区版单机 原生分布式(依赖外部存储) 多活集群,强一致性
事务支持 ACID 完整 取决于后端存储 ACID(单节点);集群弱化
部署复杂度 极低(开箱即用) 高(需搭 Hadoop/大数据栈) 中(自带集群管理)
典型规模 百亿节点以内 千亿级,海量数据 百亿节点,混合模型

单看表格可能不够直观。我来拆解一下每个库在真实药物图谱项目里的表现。

2.2 Neo4j:快速原型与中等规模首选

我个人习惯把 Neo4j 当作「图数据库中的 MySQL」。安装简单,社区活跃,Cypher 查询写起来很顺手。

我曾经接手一个药物-靶点-疾病关联图谱,一开始只有 500 万节点、2000 万关系。用 Neo4j 社区版,单机部署,索引优化好之后,跳数查询基本在 50ms 以内。团队里新来的实习生两天就能上手写 Cypher。

适用场景:数据量 < 10 亿节点、团队图查询经验不足、需要快速验证业务逻辑。

但注意一个坑——写入瓶颈。Neo4j 单机写入受限于磁盘 I/O,批量导入可以用 neo4j-admin import,但如果你的业务需要高频实时写入,千万要小心。

我踩过的坑:有一次做实时药物相互作用流处理,每秒写入 2000 条关系,Neo4j 社区版直接卡死。后来只能做削峰填谷,改成批处理才稳住。

典型的 Cypher 写法:

// 查询某个药物作用的靶点,再跳转到相关疾病
MATCH (d:Drug {name: '阿司匹林'})-[:TARGETS]->(t:Target)
OPTIONAL MATCH (t)-[:INVOLVES]->(dis:Disease)
RETURN d.name, t.name, dis.name
LIMIT 100

这个查询在索引命中的情况下,亿级数据也能秒出。但如果你做了全表扫,那就要命了——所以我建议生产环境一定要给所有查询字段建索引。

2.3 JanusGraph:海量数据的硬核选择

如果你的药物图谱达到百亿节点级别,并且需要分布式横向扩展,那 JanusGraph 值得认真考虑。它本身不存数据,数据放在 HBase 或 Cassandra 里,计算层可以水平扩展。

但老实说,部署门槛真不低。我记得第一次搭 JanusGraph 集群,光是调通 HBase + Elasticsearch(索引后端)就花了一周。要是团队里没有懂 Hadoop 生态的人,我建议先评估一下成本。

# JanusGraph 配置示例(conf/gremlin-server.yaml)
host: 0.0.0.0
port: 8182
graphs: {
  graph: conf/janusgraph-hbase.properties
}
scriptEngines: {
  gremlin-groovy: {
    plugins: {
      org.janusgraph.graphdb.tinkerpop.plugin.JanusGraphGremlinPlugin: {}
    }
  }
}
我的经验:JanusGraph 的 Gremlin 查询写法比 Cypher 抽象一层。例如同样查药物靶点,Gremlin 写起来像这样:
g.V().has('Drug', 'name', '阿司匹林')
    .out('TARGETS').hasLabel('Target')
    .out('INVOLVES').hasLabel('Disease')
    .valueMap('name')

Gremlin 的遍历式思维需要适应一阵子。我团队里不少开发习惯用 Cypher,切到 Gremlin 后写错了两周才上手。所以选型时也要考虑团队技术栈。

适用场景:数据量 100 亿+、已有 Hadoop/大数据基础设施、需要全局图分析(如 PageRank、社区发现)。

2.4 ArangoDB:多模型灵活性

ArangoDB 比较特殊——它不但是图数据库,还是文档数据库和 KV 存储。如果你在药物图谱里需要同时存结构化表格数据、JSON 文档和图关系,ArangoDB 可以一张表搞定。

它的 AQL 查询语言有点像 SQL 加图遍历,我团队里做后端的人学起来很快。但 ArangoDB 的图遍历性能在深度跳数时会有衰减,实测 6 跳以上就不如 Neo4j 了。

// AQL 查询:药物→靶点→疾病
FOR d IN Drug
  FILTER d.name == '阿司匹林'
  FOR t IN OUTBOUND d TARGETS
    FOR dis IN OUTBOUND t INVOLVES
      RETURN {drug: d.name, target: t.name, disease: dis.name}

注意:ArangoDB 的智能图(SmartGraph)在集群模式下能切分数据,但做跨分片的高跳数查询时网络开销很大。我曾在 8 节点集群上跑 10 跳全图路径,等了 30 秒才出结果——这种场景得考虑用 JanusGraph。

2.5 选型决策框架

说了这么多,到底怎么选?我总结了几个问题,你对照着问自己就行:

  1. 数据规模多大? 十亿以下 → Neo4j;百亿以上 → JanusGraph;中间态 → 看其他因素。
  2. 团队会什么? 会 Cypher → Neo4j;会 Gremlin → JanusGraph;会 SQL → ArangoDB 门槛最低。
  3. 需要事务吗? 强 ACID → Neo4j 或单机 ArangoDB;最终一致可接受 → JanusGraph。
  4. 部署运维成本? 没人运维 → Neo4j 社区版;有专职 DBA → JanusGraph;折中 → ArangoDB。

下面这张图总结了三者的决策路径:

图数据库选型决策流程 评估需求 数据规模 < 10亿? (节点+关系) ✅ Neo4j 快速原型 / 中小规模 是 需要原生分布式? (集群水平扩展) 否 ✅ JanusGraph 海量数据 / 大数据生态 是 需要多模型混合存储? (文档+图+KV) 否 ✅ ArangoDB 多模型 / 灵活查询 是 考虑团队 & 运维成本 重新评估需求 💡 决策提示 数据量中等、多模型 → ArangoDB 海量、要分布式 → JanusGraph 快速验证、强事务 → Neo4j

2.6 我的最终建议

如果你现在让我给药物图谱项目做选型,我会这么干:

  • 第一阶段(原型验证):无脑上 Neo4j 社区版,用 Docker 5 分钟跑起来。快速验证查询逻辑和数据模型。
  • 第二阶段(生产上线):如果数据量在 5 亿节点以内,且不需要分布式,继续用 Neo4j 企业版,花钱买省心。
  • 第三阶段(海量扩展):数据超过 20 亿节点,或者需要多机房部署,迁移到 JanusGraph。嗯,迁移过程很痛苦,所以一开始就要留好数据导出接口。
  • 特殊情况(混合模型):如果图谱里混着很多半结构化的临床文档,同时又要做图分析,直接上 ArangoDB 一张表搞定。
我的小技巧:不管选哪个库,先把索引设计做好。我在多个项目里发现,80% 的性能问题源于索引缺失或设计不合理。先用少量数据建索引、跑查询、看执行计划,再放全量数据。

选型没有标准答案,但有一条铁律:不要为了技术而技术。选团队最熟悉、运维成本最低、能满足三年内数据增长的方案,通常就是最优解。