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 | ||
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 版本的构建产物。
试过的告诉我,哪个算法在你的数据上最有用。
● ● ●
参考来源
- 01
Apache AGE 仓库与提交历史:https://github.com/apache/age/commits/master - 02
Apache AGE 发布记录:https://github.com/apache/age/releases - 03
Apache Madlib:https://github.com/apache/madlib - 04
pgRouting:https://github.com/pgRouting/pgrouting - 05
petgraph(Rust 图库):https://github.com/petgraph/petgraph - 06
pgrx(PostgreSQL Rust 扩展框架):https://github.com/pgcentralfoundation/pgrx - 07
pg_petgraph:https://github.com/alitrack/pg_petgraph