alitrack

pg_petgraph:PostgreSQL 缺了十年的图算法插件

PostgreSQL 有 PostGIS 管地理、pgvector 管向量、TimescaleDB 管时序,唯独没有一个轻量的图算法插件。pg_petgraph 补的就是这块:10 个算法,一行 CREATE EXTENSION。

地理空间有 PostGIS,全文搜索有 pg_bigm,时序有 TimescaleDB,向量有 pgvector。但有一个基础能力长期缺席:没有一个轻量的图算法插件。

不是你不需要。是你的数据里有图,你只是没把它当图用。

● ● ●

AGE 做图查询不做图分析,Madlib 太重,pgRouting 只管路径

先看 PG 生态里现有跟"图"沾边的三个选项:

Apache AGE。2020 年从 AgensGraph 分出来捐给 Apache,目标是把 openCypher 图查询语言带进 PG。它并不冷清——近 90 天有 30 个提交,最近一次是 2026-09-14;最新 release 是 PG18/v1.8.0-rc0(2026-07-09),PG17/v1.7.0-rc0(2026-02-11)。但 AGE 做的是图查询(Cypher 语法、图命名空间),不是图分析——PageRank、Betweenness 这些它不提供。

Apache Madlib。机器学习的瑞士军刀,里面有 PageRank、SCC 等图算法。问题是它是一个完整 ML 套件,依赖 Python + NumPy + SciPy 一大串。你只是想跑个 PageRank,它让你装半个 Anaconda。

pgRouting。路径规划专用——Dijkstra、A*、TSP,为地理网络优化的。做交通分析很合适,做社交网络分析对不上。

这三个恰好构成一个三不管地带:AGE 做图查询但不做图分析,Madlib 做图分析但不轻量,pgRouting 做路径但不做中心性。PageRank、Betweenness、社区发现,这些最常用的图算法,在 PG 里没有一个能顺手拿来用的轻量实现。

● ● ●

pg_petgraph:10 个算法,一行 CREATE EXTENSION

所以我写了一个。叫 pg_petgraph。

CREATE EXTENSION pg_petgraph;

然后就可以在 SQL 里直接跑图算法。所有函数都是同一个接口:传两个数组(sources、targets)表示边列表,返回一张表。

-- 谁是这个网络里最重要的节点?
SELECT * FROM pagerank(
  ARRAY[1, 2, 3, 2, 4],
  ARRAY[2, 3, 1, 4, 1]
);
-- 返回 node_id | score,按 score 降序

-- 有哪些紧密的小圈子?
SELECT * FROM louvain(
  ARRAY[1, 1, 2, 3, 4, 4],
  ARRAY[2, 3, 3, 4, 5, 6]
) ORDER BY community_id, node_id;
-- 返回 node_id | community_id,同一个 ID 就是同一个社区

一共 10 个函数,覆盖中心性、连通性、路径、社区发现四类:

函数
类型
干什么的
pagerank
中心性
节点在网络里的"重要性"
betweenness
中心性
节点作为"桥梁"的程度
closeness
中心性
节点到其他节点的距离
eigenvector
中心性
与重要节点相连的节点更重要
scc
连通性
强连通分量,紧密互连的群组
connected_components
连通性
弱连通分量,忽略方向的连接关系
dijkstra
路径
单源最短路径
toposort
排序
DAG 的拓扑排序
is_cyclic
检测
图里有没有环
louvain
社区发现
自动发现社区结构

全部用 Rust + pgrx 写,算法来自 petgraph,编译进同一个 .so——没有 Python 运行时,没有额外服务,没有数据序列化。编译产物就是 .so + .control + .sql 三个文件,MIT 许可。仓库里带一套 pg_test,CI 在 PostgreSQL 16 / 17 / 18 上各跑一个 job。

PageRank:谁说了算

PageRank 是最经典的图中心性算法。在一个有向图里,被"重要"节点指向的节点也重要。参数可调:

SELECT * FROM pagerank(sources, targets,
  damping => 0.85,   -- 阻尼系数,默认 0.85
  max_iter => 100    -- 最大迭代次数
);

结果按 score 降序,第一行就是最重要的节点。

Betweenness:谁在当"中间人"

Betweenness 度量一个节点在多少条最短路径上。社交网络里,betweenness 高的是"信息枢纽"——不在群聊中心,但每个群聊里都有人认识他。

SELECT * FROM betweenness(sources, targets) ORDER BY centrality DESC;

Louvain:自动发现社区

Louvain 是当前最常用的社区发现算法,能自动把网络拆成内部紧密、外部稀疏的群组。

SELECT * FROM louvain(sources, targets) ORDER BY community_id, node_id;

每个节点得到一个 community_id,同一个 ID 的就是同一个社区。

● ● ●

为什么用 pgrx 而不是 PL/Python

你当然可以用 PL/Python + networkx 在 PG 里跑图算法。问题是:networkx 是纯 Python,大图上性能差;要维护 Python 运行时和一堆依赖;数据还要在 PG 和 Python 之间来回序列化。

pgrx 把 Rust 代码编译成 PG 的原生扩展——数据和算法在同一个进程、同一块内存里,不用过一趟 Python。petgraph 是 Rust 生态里最常用的图库,算法实现成熟。

● ● ●

适用场景

  • 用户关系分析:pagerank 找关键节点,louvain 找小圈子
  • 金融反欺诈:scc 发现资金流转环路,connected_components 发现关联账户群
  • 依赖分析:toposort 排任务依赖,is_cyclic 检测循环依赖
  • 网络分析:closeness、eigenvector 排序节点影响力

分析全程在 SQL 里完成,不需要把数据导到 Spark 或 Python 再算回来。

PG 里跑图分析的真实需求,集中在「数据本来就在 PG 里、图规模中等」这一类场景——几万到上百万条边,够用,而且不想为此再起一套 Spark 或图数据库。它的立足点就在这儿:AGE 要你学 Cypher 并建图对象,Madlib 要你装半个数据科学栈,而 pg_petgraph 就是一堆 SQL 函数——会写 SQL 就会用,对已经有 PG 的人来说试用成本接近零。

这套结论的边上还有三处我没兜住:大图没测过,我手上没有百万边以上的真实数据跑基准,算法是内存建图,图太大就是 OOM,不是"慢一点";这些算法目前都是无权图上的实现,带权只有 dijkstra 能算距离,其他算法不吃权重;如果你更愿意把数据导出到 DuckDB、Spark 或专门的图数据库算图,那它的定位就只是"顺手能用",而不是"必须用"。

● ● ●

在线等

如果你用 PostgreSQL 做数据分析,这个插件可能会帮你省掉很多次 pg_dump | python | INSERT 的来回。

GitHub: https://github.com/alitrack/pg_petgraph

装法:cargo pgrx install --release,或者从 release 页下载对应 PG 版本的构建产物。

试过的告诉我,哪个算法在你的数据上最有用。

● ● ●

参考来源

  1. 01
    Apache AGE 仓库与提交历史:https://github.com/apache/age/commits/master
  2. 02
    Apache AGE 发布记录:https://github.com/apache/age/releases
  3. 03
    Apache Madlib:https://github.com/apache/madlib
  4. 04
    pgRouting:https://github.com/pgRouting/pgrouting
  5. 05
    petgraph(Rust 图库):https://github.com/petgraph/petgraph
  6. 06
    pgrx(PostgreSQL Rust 扩展框架):https://github.com/pgcentralfoundation/pgrx
  7. 07
    pg_petgraph:https://github.com/alitrack/pg_petgraph