用 Postgres 统一事务与分析数据:pg_lake 带来的新思路

2026-05-14 31 预计阅读时间:1 分钟
来源:postgr.es AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:9 分钟

5 月的 Prairie Postgres Meetup 在芝加哥创新中心迎来了首场活动,Elizabeth Christensen(Snowflake)分享了主题演讲 pg_lake: Unifying transactional and analytical data with Postgres。核心命题很直接——能不能让同一套 Postgres 既跑在线事务,又跑分析查询,而不必维护两套独立系统?

这个话题之所以值得关注,是因为"事务库 + 分析库"的双栈架构几乎是每个中等规模团队的标配:Postgres 承载业务写入,Snowflake/BigQuery 负责报表和聚合。双栈意味着数据同步、Schema 对齐、延迟容忍等一系列运维负担。pg_lake 的方向是把这些负担收进 Postgres 生态内部。

事务与分析分栈的现实痛点

典型的数据架构是这样的:

  • 业务系统写入 Postgres(OLTP)
  • ETL 定期把数据搬到 Snowflake/Redshift(OLAP)
  • 分析师在 OLAP 平台上跑聚合查询

问题出在"搬"这一步:

  1. 延迟:ETL 通常是小时级甚至天级调度,业务团队想看"过去 5 分钟的转化率"就很难。
  2. Schema 漂移:业务表改了字段,ETL 没跟上,分析结果就静默出错。
  3. 双份运维成本:两个平台各自的权限、监控、容灾。

pg_lake 想做的事情,本质上是在 Postgres 内部打通一条通往外部分析存储的管道,让事务查询和分析查询可以在同一个 SQL 接口下完成。

pg_lake 的设计意图

从演讲标题可以推断,pg_lake 的定位是 Postgres 的一个扩展(extension),它让 Postgres 能够直接查询外部对象存储(如 S3 上的 Parquet 文件)或分析型数据库中的数据,而不需要先把数据导入 Postgres 表。这样做的好处:

  • 事务数据留在 Postgres 本地表,保证 ACID。
  • 分析数据留在成本更低的对象存储或列式引擎中,通过 pg_lake 以 FDW(Foreign Data Wrapper)风格就地查询。
  • 两种数据可以在一条 SQL 里 JOIN。

这和 Postgres 已有的 FDW 机制(postgres_fdwparquet_fdw 等)思路相近,但 pg_lake 可能进一步优化了列式数据的读取路径和查询下推。

在 Postgres 中实践事务/分析一体化:可落地的方案

pg_lake 尚在演进中,但今天你就可以用 Postgres 自身能力搭建一个"轻量 HTAP"原型。以下是一个可复制的实践方案——用 postgres_fdw 把分析库的表映射到事务库,实现跨库 JOIN 查询。

步骤 1:准备两个 Postgres 实例

假设你在同一台机器上跑两个实例(事务端口 5432,分析端口 5433):

# 初始化分析实例的数据目录
initdb -D /tmp/pg_analytics_data

# 启动分析实例,端口 5433
pg_ctl -D /tmp/pg_analytics_data -o "-p 5433" -l /tmp/pg_analytics_log start

# 在分析实例上创建列存风格的宽表(用 citus 或原生 Postgres 均可)
psql -p 5433 -c "
CREATE DATABASE analytics;
"

psql -p 5433 -d analytics -c "
CREATE TABLE order_events (
    event_id    BIGINT PRIMARY KEY,
    order_id    BIGINT,
    event_type  TEXT,
    amount      NUMERIC(12,2),
    occurred_at TIMESTAMPTZ
);
INSERT INTO order_events SELECT
    generate_series(1, 100000),
    (random() * 10000)::INT,
    CASE WHEN random() < 0.6 THEN 'purchase'
         WHEN random() < 0.8 THEN 'refund'
         ELSE 'cancel' END,
    (random() * 500)::NUMERIC(12,2),
    now() - (random() * interval '30 days');
"

步骤 2:在事务库上挂载 FDW

-- 连接到事务实例(端口 5432)
psql -d myappdb

-- 安装 postgres_fdw 扩展
CREATE EXTENSION postgres_fdw;

-- 创建外部服务器,指向分析实例
CREATE SERVER analytics_server
  FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (host 'localhost', port '5433', dbname 'analytics');

-- 创建用户映射(用当前连接用户)
CREATE USER MAPPING FOR current_user
  SERVER analytics_server
  OPTIONS (user '你的系统用户名');

-- 导入分析库的表
IMPORT FOREIGN SCHEMA public
  LIMIT TO (order_events)
  FROM SERVER analytics_server
  INTO public;

-- 验证:外部表已可见
\d order_events

步骤 3:跨库 JOIN——事务表 + 分析表一条 SQL 出结果

假设事务库里有 orders 表,分析库有 order_events 表,你想查"每笔订单的退款总额":

-- 事务库本地表
CREATE TABLE orders (
    id        BIGINT PRIMARY KEY,
    customer  TEXT,
    status    TEXT
);

-- 插入一些示例数据
INSERT INTO orders SELECT
    generate_series(1, 10000),
    'customer_' || (random() * 100)::INT,
    CASE WHEN random() < 0.9 THEN 'active' ELSE 'closed' END;

-- 跨库 JOIN:事务 orders + 分析 order_events
SELECT
    o.id          AS order_id,
    o.customer,
    COALESCE(SUM(e.amount), 0) AS refund_total,
    COUNT(e.event_id)           AS event_count
FROM orders o
LEFT JOIN order_events e ON e.order_id = o.id AND e.event_type = 'refund'
GROUP BY o.id, o.customer
ORDER BY refund_total DESC
LIMIT 20;

这条查询在事务库上执行,order_events 的数据通过 FDW 从分析实例实时拉取。你不需要做 ETL,不需要等调度窗口,数据延迟等于网络延迟。

注意事项

  • FDW 查询不总是高效:大表全表扫描会逐行拉取,务必在远程表上建合适索引,或在 IMPORT FOREIGN SCHEMA 时用 OPTIONS (use_remote_estimate 'true') 让优化器参考远端统计信息。
  • 事务库和分析库的资源隔离很重要:分析查询可能吃大量内存和 CPU,生产环境中建议把分析实例放在独立机器上,或用连接池限制并发。
  • 上面的示例用两个 Postgres 实例模拟,真实场景中分析端可以是 Citus 集群、Parquet 文件(通过 parquet_fdw)甚至 Snowflake(如果 pg_lake 成熟后)。

从双栈到单栈:取舍清单

维度 双栈(Postgres + Snowflake) 单栈(Postgres + pg_lake/FDW)
查询性能(大规模聚合) Snowflake 列存 + 弹性集群,优势明显 Postgres 行存为主,超亿行聚合需 Citus 或外部列存
数据新鲜度 受 ETL 调度限制 FDW 实时读取,秒级
运维复杂度 两套平台、两套权限 一套 Postgres 生态,FDW 配置相对轻
成本 Snowflake 按查询量计费 对象存储 + Postgres 实例,通常更可控
生态成熟度 十年工业级验证 pg_lake 刚起步,FDW 方案成熟但性能有边界

务实建议

  1. 如果你的分析数据量在千万行以内、聚合查询并发不高,FDW 方案已经够用——今天就能落地。
  2. 如果分析负载重(TB 级、高并发聚合),保留独立分析引擎更稳妥,但可以用 pg_lake 做实时补充查询,替代部分 ETL。
  3. 关注 pg_lake 的后续发布,它的价值在于把 FDW 的"手动接线"变成标准化的、针对列存优化的内置通道。

6 月 4-5 日的 PG DATA 和 7 月 15 日的下一次 Meetup 会是跟进这个方向的好机会。统一事务与分析不会一步到位,但 Postgres 生态正在一步步缩小这个间隙。


相关推荐