内容提要
pg_knowledge_base 是 PostgreSQL 19 的扩展,将 Oxigraph 的 SPARQL 引擎嵌入数据库,无需额外三元组存储。三元组存于普通表,现有表可通过 R2RML 映射为 RDF,一条 SPARQL 查询可同时访问两者。事务、复制、备份和权限沿用 PostgreSQL,端点支持标准 SPARQL 客户端。该扩展基本通过 W3C 测试,查询性能优于 RocksDB,但加载更慢、占用磁盘更多。
延伸解读
统一事务与运维的取舍
文章的核心价值在于消除独立三元组存储带来的运维分裂:行与三元组共享同一事务、备份、复制和权限体系,避免ETL副本过期和跨库事务缺失。但代价是存储层从RocksDB换成普通表,加载更慢、磁盘占用约为Oxigraph的5倍,主要因btree索引缺少前缀压缩。读者需权衡:若更看重数据一致性和运维简化,这一方案有吸引力;若对加载速度和存储成本敏感,则需谨慎。
查询性能并非全面占优
基准测试显示,嵌套循环索引查找类查询在PostgreSQL上快4到8倍,但点查询在SQL路径下仅0.14毫秒,端点路径反而略慢于Oxigraph。作者指出Oxigraph默认仅32MB RocksDB块缓存,扩大缓存后可能缩小差距。因此性能结论受缓存配置影响,不能简单理解为PostgreSQL全面胜出。读者应关注自身查询模式:若以复杂连接和过滤为主,该扩展可能更合适;若以简单点查为主,优势有限。
功能边界与适用场景
文章明确列出限制:R2RML映射按模式逐条读取,连接、过滤和聚合在spareval中执行而非下推为单条SQL;SPARQL更新不会写入映射表;不支持SERVICE联邦;端点仅HTTP/1.1加基础认证;kb.quads不支持行级安全;优化器尚无统计信息。这些限制意味着它适合本体、分类法和快速变化事实与关系表并存的场景,但不适合需要联邦查询或对映射表做SPARQL写入的用例。
Q&A
pg_knowledge_base 是什么?它解决了什么问题?
pg_knowledge_base 是 PostgreSQL 19 的扩展,将 Oxigraph 的 SPARQL 引擎嵌入数据库内部,无需额外三元组存储。它解决了知识图谱需要单独维护三元组数据库带来的成本:数据需 ETL 复制且易过期、两套安全/备份/故障转移、无法跨行和三元组事务。
这个扩展如何让 SPARQL 查询同时访问三元组和普通表?
三元组存储在普通表 kb.quads 中,现有表通过 R2RML 映射为 RDF(不复制数据)。一条 SPARQL 查询可以同时使用存储中的三元组和映射表的数据,例如用 skos:broader* 遍历分类法,同时从 employees 表读取 foaf:name 和 ex:dept。
pg_knowledge_base 的事务和复制行为是怎样的?
kb.sparql_update() 在调用者事务中运行,行更新和三元组更新一起提交或回滚。存储是堆表和 btree 索引,所有 SPARQL 写入走 WAL,因此流复制和逻辑复制都支持:热备库可回答 kb.sparql() 查询(包括 R2RML 映射),但拒绝更新;逻辑复制可发布 kb.quads、kb.terms、kb.graphs、kb.mappings 及映射表。
与 Oxigraph 自带的 RocksDB 存储相比,pg_knowledge_base 的性能如何?
在 357 万三元组的 BSBM 数据集上,嵌套循环索引查找类查询在 PostgreSQL 上快 4 到 8 倍(因 shared_buffers 缓存整个存储,而 Oxigraph 默认仅 32MB 块缓存)。但加载更慢(43.8 秒 vs 1.5 秒,bulk 模式 19.1 秒)且占用磁盘更多(1,613 MB vs 324 MB),主要因 btree 索引缺少前缀压缩和 LZ4。
SPARQL 客户端如何连接这个扩展?认证和权限如何工作?
扩展提供 SPARQL 1.1 协议和 Graph Store 协议端点,路径以数据库名开头(如 /company/query)。端点用户是普通 PostgreSQL 角色,通过 pg_hba.conf 和密码认证,权限用普通 GRANT 控制(查询需 SELECT on kb schema,更新需 INSERT/DELETE on kb.quads 等)。每个请求是一个事务,可在 pg_stat_activity 中查看并用 pg_cancel_backend() 取消。
pg_knowledge_base 有哪些已知限制?
R2RML 逐模式读取,映射表上的连接、FILTER 和聚合在 spareval 中运行而非单个 SQL 查询;SPARQL 更新从不写入映射表;不支持 SERVICE 联邦;端点仅 HTTP/1.1 和基本认证;行级安全对映射表有效但对 kb.quads 无效;类型化字面量保留为值;存储尚未向优化器提供统计信息。