是什么
图数据库把数据存成顶点(实体)与边(关系),查询沿着关系指针做遍历,而不是在查询时反复用 join 拼接。当「关系本身」就是查询主体时——多跳路径、最短路径、环路、社区——图模型的表达与性能优势才成立;层级浅、模式固定的场景,文档库的递归查询或关系库的递归 CTE 往往更划算。
基本信息
| 适用场景 | 社交关系、反欺诈环路、权限继承、知识图谱、路径与推荐 |
|---|---|
| 不适合 | 以点查和全量统计报表为主的负载:图库不擅长全表扫描与大批量聚合 |
| 常见实现 | Neo4j(Cypher)、JanusGraph、TigerGraph;查询语言还有 Gremlin、SPARQL |
| 替代方案 | 浅层层级用 MongoDB $graphLookup;两点间固定关系用关系库 join;全量统计交给列式库 |
| 关键风险 | 超级节点:单个顶点挂载百万级边时,遍历代价急剧上升 |
典型使用场景
- 多跳关系查询:找出「好友的好友中尚未关注我的人」,关系库要写多层自连接,图库一句模式匹配
- 最短路径与可达性:网络拓扑、供应链、依赖关系里判断两点是否连通及其最短链路
- 环路检测:反欺诈中识别互相关联的账号团伙,资金或设备共享形成的闭环
- 权限继承:组织树与角色继承下的有效权限推导,改一处关系即可反映到所有下游
- 推荐与相似度:共同邻居、社区划分,用于「你可能认识」类功能
- 知识图谱:实体与关系的密集存储,配合全文检索做结合查询
Cypher 查询示例(Neo4j 语法)
Cypher 查询示例(Neo4j 语法)
// 两跳之内可能认识的人(排除已关注的)
MATCH (me:User {id: 7})-[:FOLLOWS]->(b)-[:FOLLOWS]->(c)
WHERE NOT (me)-[:FOLLOWS]->(c) AND c <> me
RETURN c.id, count(*) AS paths
ORDER BY paths DESC LIMIT 10;
// 带深度上限的可变长路径,避免无界遍历
MATCH p = (me:User {id: 7})-[:FOLLOWS*1..3]->(t:User)
RETURN t.id, length(p) AS hops LIMIT 20;
// 两点之间的最短路径
MATCH (a:User {id: 7}), (b:User {id: 42}), p = shortestPath((a)-[:FOLLOWS*..6]-(b))
RETURN length(p);按需求选方案
| 需求特征 | 推荐方案 | 原因 |
|---|---|---|
| 固定两点、已知层级的关联 | 关系库 join 或文档库 $lookup | 模型简单,无需引入新组件 |
| 单集合内浅层递归(组织树、物料层级) | MongoDB $graphLookup 配 maxDepth | 复用现有存储,改动最小 |
| 多跳、变长路径、最短路径 | 图数据库 | 沿指针遍历,深度增加时代价增长平缓 |
| 环路与社区识别 | 图数据库或图算法库 | 图算法是原生能力 |
| 全量报表与聚合统计 | 列式库或数据仓库 | 图库在这种负载上明显吃亏 |
引入图库前先用真实数据验证核心查询:很多「看起来像图」的需求,本质是浅层过滤加聚合,用现有栈就能满足;图库带来的是新的备份、监控、扩容与数据同步成本。
超级节点是图库最常见的性能陷阱:一个热门账号或一台核心设备挂载百万级边时,遍历会退化成扫描这些边。建模阶段要评估边的度数分布,对超级节点做拆分或限制遍历深度。