用 PostgreSQL 实践 Palantir 本体论

作者简介:怀玉杰,瀚高股份研发工程师,负责 AI 方向研发,擅长算法分析与 AI 应用。

医院数据管理的挑战

介绍

当前医院的信息系统呈现出多系统并存的复杂局面。一家三甲医院通常运行着数十个不同的业务系统:HIS(医院信息系统)处理核心业务,EMR(电子病历系统)记录诊疗过程等。并且医院场景本身复杂多变,患者从入院到出院整个过程往往要经历多个阶段:入院登记、床位分配、科室调整、检查与治疗、最终出院。

以床位管理为例,护士寻找空床需要反复在系统查询和电话确认之间切换,效率低下且容易出错。当前主流医院系统设计是状态驱动的建模方式,只记录当前状态,如:在患者表中维护当前状态(在院/出院/转科中),无法追溯历史变化,随着数据增多、业务繁杂,各种问题也逐步暴露。

python 复制代码
CREATE TABLE beds (
	bed_id uuid DEFAULT gen_random_uuid() NOT NULL,
	bed_number varchar(100) NOT NULL,
	department_id uuid NULL,
	bed_type varchar(20) NULL CHECK (bed_type IN ('普通床', 'ICU床','隔离床', '抢救床','儿科床')),
	equipments jsonb NULL,
	current_status varchar(20) NULL CHECK (current_status IN ('占用','空闲','清理中')),
	physical_location jsonb NULL,
	support_isolation bool DEFAULT false NULL,
	specialty_attribute text NULL,
	created_at timestamptz DEFAULT now() NULL,
	updated_at timestamptz DEFAULT now() NULL
);

当前问题

首先是可追溯性问题。当系统只保留"当前状态"时,无法进行历史追溯、操作追溯,很难回答看似简单的问题:谁用过这张床?病人为什么转科?床位状态为什么是这样?

其次是逻辑分散、维护成本高的问题。技术实现中,每个业务操作需要编写专门的存储过程(procedure),且牵扯多种函数或表关系,当业务规则发生变化时,往往需要同时修改多处代码且新增业务类型时,需要考虑对现有流程的影响。随着业务流程的复杂,会导致系统越来越臃肿,最终复杂的存储过程与触发器会难以理解和调试,成本也会越来越高。

最后是系统语义模糊的问题。在状态驱动模型中,数据库中的一行记录,往往混合了三种含义:现实世界发生过什么;系统当前认为是什么状态;流程执行到了哪一步。这三者在数据层面被耦合在一起,使得系统越来越像一个"黑盒"。

综上所述,医院这种高度依赖时间、行为和约束,且场景多样复杂,行为动态变化的需求下,我们需要新的数据管理思维去建立新的系统。以床位系统为例,需要有以下优点:

  • 完整的历史追溯:能还原床位状态的完整演变过程。
  • 数据一致性:避免多系统间的数据矛盾。
  • 操作透明性:每个状态变化都有明确的上下文记录。
  • 扩展灵活性:新业务能快速上线,不影响现有功能。
  • 分析支持能力:基于历史数据提供决策支持。

因此,我们希望系统能够完整记录整个过程,状态只是从事实中推导出的结果。

Palantir 方法论

方法论简介

Palantir 提出了以 Ontology(本体论) 为核心的数据建模方法论,并在复杂业务系统中,将"行为(Action)"而非"状态(State)"放在系统的中心位置。

本体论是一种工程化的数据建模方法,其核心观点是:信息系统不应该关注"状态",而应该关注"发生了什么",然后从这些事实中推导出当前状态。

'行为记录'并不意味着把所有业务逻辑都放在数据库中。相反,本体论倡导清晰的职责分离:应用层负责业务流程的编排和规则执行,而数据库层则专注于忠实地记录这些流程产生的'行为'。这种分离使得系统既能享受行为驱动的追溯能力,又能保持架构的灵活性和可扩展性。

以床位系统为例:本体论不是记录"床位现在是空的",而是记录"病人 A 于 10:00 从床位 1 出院了",然后推导出"床位 1 现在是空的"。

在这种模型下,系统的职责不再是不断"修改状态",而是完整、准确地记录每一次行为的发生。一旦行为被记录下来:状态可以随时重新;计算历史可以完整回放;业务决策可以基于事实进行分析。

对比

我们以患者转科的例子来比较传统思维与 Ontology 的区别:

  1. 传统转科思维模式:
  • 更新患者表的状态:

UPDATE patient SET department_id = '心内科' WHERE patient_id = '001';

  • 更新床位表的状态

UPDATE bed SET current_status = '清理中' WHERE bed_id = 'B01';

UPDATE bed SET current_status = '占用' WHERE bed_id = 'B02';

  1. Palantir 思维模式:
  • 在行为表中记录一个不可变的事实
python 复制代码
INSERT INTO bed_events (
    patient_id,
    event_type,
    event_time,
    details
) VALUES (
    '001',
    '占用',
    '2024-01-15 14:30:00',
    '{
        "department": "心内科",
        "bed": "B01",
        "reason": "确诊冠心病需专科治疗",
        "doctor": "张明",
        "order_id": "ORDER_789"
    }'::JSONB
);
  • 自动更新床位的视图
python 复制代码
CREATE VIEW current_bed_status AS
WITH latest_bed_events AS (
    SELECT DISTINCT ON (bed_id) *
    FROM bed_events
    ORDER BY bed_id, event_time DESC
)

优势

通过上述对比,我们可以总结出以下优势:

  1. 业务优势:
  • 完整溯源:能够回答"病人为什么转科"、"床位谁用过"这类历史问题。

  • 数据一致性:所有系统基于相同的事实记录,避免状态不一致。

  • 业务灵活性:新增业务流程只需定义新的事实类型,无需修改现有结构。

  1. 技术优势:
  • 系统解耦:事实记录层与业务逻辑层分离。

  • 简化维护:无需复杂的存储过程链,核心逻辑是记录事实。

  • 便于分析:所有历史数据都在,方便进行趋势分析和决策支持。

医院业务的复杂性不仅在于流程多,更在于每个流程都需要完整的溯源能力。无论是医疗质量管理、费用追溯,还是医疗纠纷处理,都需要能够回答"当时发生了什么"。Palantir 的本体论解决了这一问题:不再试图维护一个"完美"的当前状态,而是忠实地记录所有重要事实,让状态成为事实的自然推导结果。

PostgreSQL :Palantir 思想的天然数据基石

PostgreSQL 的优势

这种思想转变带来了数据管理范式的革新,但要真正落地,我们需要一个能够有效支持这种数据模型的技术平台。在实践中,PostgreSQL 是本体论实现的天然数据基石。

以医院系统为例,有以下契合点:

  1. 记录事实:

本体论的核心在于事实优先,而相较于传统数据库,PostgreSQL 在事实型数据建模方面具备天然优势:

  • JSONB 类型:可存储任意结构的上下文数据,适合事实表的构建,当业务流程变化时,无需频繁修改表结构,只需在 JSONB 中扩展新的字段即可。
  • 时间类型丰富:PostgreSQL 提供了多种时间类型,并支持时区转换,适合精确描述行为发生的完整时间维度。
  • 表继承与分区:通过表继承能自然建立事实表的层级关系,而分区功能可以有效管理海量历史数据,提高查询性能和管理效率。
  1. 描述状态:

在本体论中,"状态"是由事实型数据推导的结果,而 PG 在这方面具备显著优势:

  • 视图与物化视图:PostgreSQL 支持复杂的视图和物化视图,可以从事实表中实时推导出当前状态。物化视图支持自动或手动刷新,在性能与实时性之间提供灵活平衡。
  • 窗口函数与聚合:PostgreSQL 拥有强大的窗口函数和聚合能力,能够基于历史事实序列计算出各种状态指标,如平均住院日、床位周转率等。
  • 递归查询支持:通过 CTE(公共表表达式)和递归查询,可以处理复杂的层次结构和时序分析,例如完整追溯患者的整个诊疗过程。
  1. 维护数据一致性:

PostgreSQL 提供了多种机制来维护事实数据的质量和一致性:

  • 事务保障:通过 ACID 事务保证事实记录的原子性和一致性,即使在高并发场景下也能确保数据完整。
  • 约束与触发器:丰富的约束类型(检查约束、唯一约束、外键约束)和触发器机制,能够在数据层自动维护数据质量,确保事实记录的准确性。
  • 并发控制:多版本并发控制(MVCC)机制确保在高并发环境下,事实记录的写入和状态查询可以高效并行执行。
  1. 特有扩展能力:

PostgreSQL 通过丰富的扩展生态系统,能够满足医疗场景中的特殊需求:

  • 空间数据分析:PostGIS 扩展支持地理空间数据存储与分析,可用于医院床位布局优化、患者动线分析等场景。
  • 外部数据集成:通过 FDW(Foreign Data Wrapper)可以透明地集成医院其他系统的数据,实现真正的数据融合,而无需复杂的 ETL 流程。
  • 时序数据优化:TimescaleDB 扩展专门优化时序数据处理,能够高效管理医院环境中产生的大量时间序列事实数据。
  • 图数据支持:Apache AGE 扩展为 PostgreSQL 增加图数据库能力,可以分析复杂的医患关系、疾病传播路径等。
  1. 生态成熟:

PostgreSQL 在生产环境中已经证明了其可靠性和稳定性:

  • 开源可控:开源许可确保医院能够完全掌握核心技术栈,避免厂商锁定风险,同时降低了软件许可成本。
  • 成熟工具链:拥有 pgAdmin、pgBackRest、pgBouncer 等成熟的运维管理工具,覆盖监控、备份、连接管理等关键运维场景。
  • 活跃社区:全球活跃的开源社区和多个商业支持厂商,确保技术问题能够快速响应和解决。
  • 云原生支持:所有主流云平台都提供托管的 PostgreSQL 服务,简化部署和运维。

PostgreSQL 的定位

综合来看,在本体论中,PostgreSQL 承担以下角色:

  • 现实世界行为的事实存储层。
  • 业务状态的推演与分析基础。
  • 多系统数据一致性的核心锚点。

这些特点使 PostgreSQL 作为数据层的坚实基础,成为本体论方法中落地的理想选择。

具体实现

在本文中,我们以医院床位管理为例,设计一个最小的 PostgreSQL Demo,用于验证本体论思路在实际业务场景中的可行性。

本体论视角下核心对象建模

在医院床位管理场景中,主要可以抽象出以下几类核心对象:

  • Patient
  • Bed
  • Department
  • Order(医嘱表):表示医生的医嘱,是意图而不是已发生的事实

这些对象本身相对稳定,业务变化不体现在对象结构上,而是体现在它们的关系变化上。

python 复制代码
create table beds(
bed_id uuid default gen_random_uuid() not null,
bed_code varchar(100) not null,
department_id uuid null,
bed_type varchar(20) null check (bed_type in ('普通床', 'icu床','隔离床', '抢救床','儿科床')),
last_changed_at timestamp
);

系统中的事实存储

在床位管理场景中,有事实存储表:bed_actions,只负责记录事实,不包含业务逻辑。需要强调的是:

  • Action 表不包含状态字段。
  • 不区分"执行中 / 已完成 / 已失败"。
  • 一条 Action 一旦写入,即被视为系统确认的事实。

这使得 Action 表天然具备以下特性:

  • 事实不可篡改。
  • 历史完整保留。
  • 行为语义清晰。
python 复制代码
create table bed_actions (
    action_id uuid primary key default gen_random_uuid(),
    action_type text not null check( action_type in ('被分配','被释放')),
    patient_id uuid not null references patients(patient_id),
    bed_id uuid references beds(bed_id),
    from_department_id uuid references departments(department_id),
    to_department_id uuid references departments(department_id),
    context jsonb,
    occurred_at timestamptz not null default now()
);

使用说明

在这个模型中表达一次转科流程,是两条 action:释放原床和分配新床。

python 复制代码
#释放原床
insert into bed_actions(
    action_type,
    patient_id,
    bed_id,
    from_department_id,
    context) values(
    '被释放',
    'Patient_01',
    'B01',
    'D01',
    jsonb_build_object(
        'reason','转科转出',
        'order_id':order_id
    )
);
#分配新床
insert into bed_actions(
    action_type,
    patient_id,
    bed_id,
    from_department_id,
    context) values(
    '被分配',
    'Patient_01',
    'B02',
    'D02',
    jsonb_build_object(
        'reason','转科转入',
        'order_id':order_id
    )
    );

若想查询"某科室有哪些空床",根据 bed_actions 表派生状态,使用 SQL 进行查询。

python 复制代码
#构建床位状态表
create view bed_current_status as
select
    b.bed_id,
    b.department_id,
    case
        when last_action.action_type = '被分配' then '占用'
        when last_action.action_type = '被释放' then '空闲'
        else '空闲'
    end as bed_status
from beds b
left join lateral (
    select *
    from bed_actions a
    where a.bed_id = b.bed_id
    order by occurred_at desc
    limit 1
) last_action on true;

#查询某科室空床
select *
from bed_current_status
where department_id = :dept_id
  and bed_status = '空闲';

总结

从状态驱动到行为驱动的转变,本质上是数据管理思维的根本革新。传统系统试图维护一个"完美的当前状态",而本体论方法选择忠实地记录"所有重要事实"。这种转变让系统具备了前所未有的追溯能力和灵活性。

PostgreSQL 凭借其强大的数据管理能力,成为这一方法落地的理想选择。它不仅提供了技术实现的可能,更重要的是其设计哲学与本体论思想高度一致:都强调数据的完整性、一致性和可追溯性。

在实际应用中,这种架构实现了职责的清晰分离:应用层专注于业务流程编排,PostgreSQL 作为数据基石。 选择 PostgreSQL,并以行为为核心建模时,许多看似复杂的问题------历史追溯、状态一致性、系统可解释性------都会在模型层面被自然化解。数据库不再只是数据的存储容器,而成为对现实世界的结构化表达。这正是本体论方法在复杂业务系统中真正的价值所在。


HOW 2026 议题招募中

2026 年 4 月 27-28 日,由 IvorySQL 社区联合 PGEU(欧洲 PG 社区)、PGAsia(亚洲 PG 社区)共同打造的 HOW 2026(IvorySQL & PostgreSQL 技术峰会) 将再度落地济南。届时,PostgreSQL 联合创始人 Bruce Momjian 等顶级大师将亲临现场。

自开启征集以来,HOW 2026 筹备组已感受到来自全球 PostgreSQL 爱好者的澎湃热情。为了确保大会议题的深度与广度,我们诚邀您在 2026 年 2 月 27 日截止日期前,提交您的技术见解。

投递链接:jsj.top/f/uebqBc

相关推荐
HelloGitHub5 小时前
《HelloGitHub》第 119 期
开源·github
冬奇Lab17 小时前
一天一个开源项目(第35篇):GitHub Store - 跨平台的 GitHub Releases 应用商店
开源·github·资讯
爱可生开源社区1 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1771 天前
《从零搭建NestJS项目》
数据库·typescript
Bigger1 天前
为什么你的 Git 提交需要签名?—— Git Commit Signing 完全指南
git·开源·github
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再2 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest2 天前
数据库SQL学习
数据库·sql