PostgreSQL Field Guide

PostgreSQL 与 DuckDB 选型

行存 OLTP 服务器与进程内列存 OLAP 引擎的分工:各自适用场景、互操作方式,以及在 AI 数据栈中的位置

PostgreSQL 是为大量并发事务设计的行存客户端/服务器数据库;DuckDB 是进程内的列存分析引擎——一个链接进应用的库,而不是一个需要连接的服务。两者经常被放在一起比较只是因为都会说 SQL,但它们回答的是不同的问题:“一千个用户能否安全地同时读写”与“单个进程能多快聚合十亿行”。

2026-08 对照官方文档核对

本页的行为陈述以 2026 年 8 月核对的双方官方文档为准:PostgreSQLDuckDB。涉及具体版本的细节请在依赖前复核。

架构对比

PostgreSQLDuckDB
存储布局行存(heap),为点查与小写入调优列存、向量化执行,为扫描与聚合调优
进程模型独立服务器;客户端经网络连接(pgwire)进程内库或 CLI;数据库就是一个文件
并发写入MVCC 下的多连接并发读写要么一个进程以读写方式打开数据库,要么多个进程以只读方式打开(access_mode = 'READ_ONLY');不支持多进程并发写入(并发文档
事务完整 ACID,可配置隔离级别单进程内的 ACID 事务
部署形态自行运维的服务器,或托管服务嵌入 Python/R/Java/Wasm/CLI,无服务可运维
扩展生态装载进服务器的扩展(pgvector、PostGIS、TimescaleDB……)可加载扩展(postgresparqueticeberg……)
服务模型在线服务、API、多租户应用本地分析、ETL、数据准备、边缘/嵌入式分析

并发写入那一行是实际的分界线:负载若是“来自多台机器的多个写入方”,DuckDB 在架构上就出局;负载若是“单个作业按磁盘允许的速度读列存数据”,客户端/服务器模型的每查询一次网络往返正是 DuckDB 所没有的开销。

什么时候各选各的

选 DuckDB

  • 对本地或对象存储上的文件(Parquet、CSV、JSON)做交互式分析,不导入任何地方。
  • 流水线或 notebook 里的数据准备与转换环节。
  • 无法附带一台服务器的边缘与嵌入式分析场景。

选 PostgreSQL

  • 有并发写入、约束与外键的多用户事务负载。
  • 任何要 7×24 小时为 API 或应用供数的场景。
  • 需要行级安全、逻辑复制、时间点恢复或扩展生态的负载——具体收益见扩展生态云服务版图

PostgreSQL 侧的分析能力边界

PostgreSQL 能正确执行分析查询,但相对列存引擎是逐行处理的;在大扫描上这个差距是结构性的,不是靠调参能消除的。不迁走 PostgreSQL 数据的前提下,有三条弥合路径:

  • 列存扩展pg_mooncake 在 Iceberg 中维护 PostgreSQL 表的列存镜像,并用 DuckDB 执行引擎加速分析;Citus 在分布式能力之外提供列存表选项。
  • 导出给 DuckDB:PostgreSQL 保持为权威数据源,定期把快照导出为 Parquet 供分析——DuckDB 原生读取 Parquet。
  • 推给数据仓库:当负载彻底超出单机时,把分析整体移到仓库层。

两者混用模式

DuckDB 读 PostgreSQL:postgres_scanner

DuckDB 官方的 postgres 扩展可以直接挂载一个在线的 PostgreSQL 数据库并对其执行查询,包括条件下推:

INSTALL postgres;
ATTACH 'dbname=app user=analyst host=127.0.0.1' AS pg (TYPE postgres, READ_ONLY);

SELECT status, count(*), avg(total_cents)
FROM pg.orders
WHERE placed_at >= now() - interval '30 days'
GROUP BY status;

这是“不导出就分析生产数据”的标准做法:DuckDB 拉取所需的行,重聚合发生在 DuckDB 的向量化引擎里。挂载时用只读模式和低权限的 PostgreSQL 角色,保证分析路径无法回写。

PostgreSQL 读文件:FDW

反方向上,PostgreSQL 的外部数据包装器可以把 Parquet 文件暴露为外部表(例如用 parquet_s3_fdw)。适合的场景是:这些文件是关系处理的输入,需要在 PostgreSQL 权限体系下与在线表 join——它并不替代 DuckDB 的扫描速度。

CREATE EXTENSION parquet_s3_fdw;

CREATE SERVER parquet_files FOREIGN DATA WRAPPER parquet_s3_fdw;

CREATE FOREIGN TABLE lake_events (...)
SERVER parquet_files
OPTIONS (dirname 's3://analytics/events/', sorted 'event_time');

server 与表级选项随 FDW 版本不同,准确写法以该扩展的 README 为准。

AI 场景对照

两个引擎通常出现在同一条流水线的不同阶段:

  • DuckDB 负责准备:把原始导出和数据湖文件清洗、join、聚合成 AI 应用真正要供数的文档与表。没有服务器要运维,产出的 Parquet 直接进入下一阶段。
  • PostgreSQL 负责在线:多租户事务状态、RAG 里 pgvector 加全文检索的混合检索,以及 Agent 长期记忆这类状态——在这些场景里,并发、权限与可审计性才是重点。

一条经验法则:正在被准备的静态数据交给 DuckDB;正在被服务给用户和 Agent 的数据放在 PostgreSQL。

AI prompt:为负载选引擎

在 PostgreSQL 与 DuckDB 之间选型
帮我为这个负载在 PostgreSQL 和 DuckDB 之间选型。

1. 负载:(数据量、读写比、查询形态)
2. 写入方:(多少进程/用户并发写、从哪里来)
3. 服务方式:(是否有在线 API/Agent 在读,还是纯离线分析)
4. 请给出:
 - 推荐 PostgreSQL、DuckDB 还是两者并用(并说明职责划分)
 - 若并用:集成方式选 postgres_scanner、Parquet 导出还是 FDW
 - 选错时最可能出现的两个故障模式
5. 约束:(运维能力、延迟预算、合规要求)

相关页面

Last updated on

On this page