PostgreSQL 19: 支持 SQL/PGQ 属性图查询能力

John Doe 三月 31, 2026

PostgreSQL 作为全球最流行的开源关系型数据库,早已通过 JSON、向量、地理信息等特性实现了多模能力的拓展,但长期以来一直缺少原生的图查询能力。

image

特性提交日志

SQL 属性图查询(SQL/PGQ)。

依据 SQL/PGQ 标准(ISO/IEC 9075-16:2023)实现 SQL 属性图查询功能。

本次更新新增:

  • 用于图模式匹配的GRAPH_TABLE表函数
  • CREATE/ALTER/DROP PROPERTY GRAPH一类 DDL 命令
  • 若干新的系统目录与信息模式视图
  • psql 中的\dG元命令
  • 用于pg_dumppsqlpg_get_propgraphdef()函数

属性图是一种新增关系类型RELKIND_PROPGRAPH的关系对象。

它在很多方面行为类似视图,在查询重写阶段会被转换为标准关系查询。

访问权限机制与安全调用者视图类似。(安全定义者模式当前暂未实现。)

讨论:https://www.postgresql.org/message-id/flat/a855795d-e697-4fa5-8698-d20122126567@eisentraut.org

特性示例

社交平台需要实现用户的好友推荐、二度 / 三度好友查询、共同好友识别等功能,是图查询最经典的应用场景。此前通过递归 CTE 实现需要数十行 SQL 代码,语义晦涩,而 SQL/PGQ 可通过极简语法实现。

准备业务表,用户表 users 是图结构的顶点,好友关系表 friendships 是图结构的边:

CREATE TABLE users (
  user_id bigint PRIMARY KEY,
  username text NOT NULL,
  gender text,
  city text
);

CREATE TABLE friendships (
  from_user_id bigint NOT NULL REFERENCES users(user_id),
  to_user_id bigint NOT NULL REFERENCES users(user_id),
  create_time timestamptz DEFAULT NOW(),
  PRIMARY KEY (from_user_id, to_user_id)
);

插入测试数据:

INSERT INTO users VALUES
(1, '张三', '男', '北京'), (2, '李四', '男', '北京'),
(3, '王五', '女', '上海'), (4, '赵六', '男', '深圳'),
(5, '钱七', '女', '北京');
INSERT INTO friendships VALUES
(1,2), (2,1), (1,3), (3,1), (2,4), (4,2), (3,5), (5,3);

创建社交关系属性图:

CREATE PROPERTY GRAPH social_graph
VERTEX TABLES (
  users KEY(user_id) LABEL person PROPERTIES (user_id, username, city)
)
EDGE TABLES (
  friendships
  KEY (from_user_id, to_user_id)
  SOURCE KEY (from_user_id) REFERENCES users(user_id)
  DESTINATION KEY (to_user_id) REFERENCES users(user_id)
  LABEL friend_of
);

执行图查询,查询用户 1 的二度好友(排除自己和直接好友):

SELECT DISTINCT username, city
FROM GRAPH_TABLE (
  social_graph
  MATCH (u:person) -[f1:friend_of]-> (f:person) -[f2:friend_of]-> (ff:person)
  WHERE u.user_id = 1
    AND ff.user_id <> u.user_id
    AND NOT EXISTS (
      SELECT 1 FROM friendships
      WHERE from_user_id = u.user_id AND to_user_id = ff.user_id
    )
  COLUMNS (ff.username, ff.city)
);

查询结果会返回用户 1 的二度好友:赵六、钱七,仅需几行 SQL 即可直观表达多跳关系查询,相比递归 CTE 代码量减少 70%,语义清晰易维护。

非常不错的体验,感谢所有参与的社区人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/2f094e7ac691abc9d2fe0f4dcf0feac4a6ce1d9c