PostgreSQL 与 DuckDB 选型
行存 OLTP 服务器与进程内列存 OLAP 引擎的分工:各自适用场景、互操作方式,以及在 AI 数据栈中的位置
PostgreSQL 是为大量并发事务设计的行存客户端/服务器数据库;DuckDB 是进程内的列存分析引擎——一个链接进应用的库,而不是一个需要连接的服务。两者经常被放在一起比较只是因为都会说 SQL,但它们回答的是不同的问题:“一千个用户能否安全地同时读写”与“单个进程能多快聚合十亿行”。
2026-08 对照官方文档核对
本页的行为陈述以 2026 年 8 月核对的双方官方文档为准:PostgreSQL 与 DuckDB。涉及具体版本的细节请在依赖前复核。
架构对比
| PostgreSQL | DuckDB | |
|---|---|---|
| 存储布局 | 行存(heap),为点查与小写入调优 | 列存、向量化执行,为扫描与聚合调优 |
| 进程模型 | 独立服务器;客户端经网络连接(pgwire) | 进程内库或 CLI;数据库就是一个文件 |
| 并发写入 | MVCC 下的多连接并发读写 | 要么一个进程以读写方式打开数据库,要么多个进程以只读方式打开(access_mode = 'READ_ONLY');不支持多进程并发写入(并发文档) |
| 事务 | 完整 ACID,可配置隔离级别 | 单进程内的 ACID 事务 |
| 部署形态 | 自行运维的服务器,或托管服务 | 嵌入 Python/R/Java/Wasm/CLI,无服务可运维 |
| 扩展生态 | 装载进服务器的扩展(pgvector、PostGIS、TimescaleDB……) | 可加载扩展(postgres、parquet、iceberg……) |
| 服务模型 | 在线服务、API、多租户应用 | 本地分析、ETL、数据准备、边缘/嵌入式分析 |
并发写入那一行是实际的分界线:负载若是“来自多台机器的多个写入方”,DuckDB 在架构上就出局;负载若是“单个作业按磁盘允许的速度读列存数据”,客户端/服务器模型的每查询一次网络往返正是 DuckDB 所没有的开销。
什么时候各选各的
选 DuckDB
- 对本地或对象存储上的文件(Parquet、CSV、JSON)做交互式分析,不导入任何地方。
- 流水线或 notebook 里的数据准备与转换环节。
- 无法附带一台服务器的边缘与嵌入式分析场景。
选 PostgreSQL
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 之间选型。 1. 负载:(数据量、读写比、查询形态) 2. 写入方:(多少进程/用户并发写、从哪里来) 3. 服务方式:(是否有在线 API/Agent 在读,还是纯离线分析) 4. 请给出: - 推荐 PostgreSQL、DuckDB 还是两者并用(并说明职责划分) - 若并用:集成方式选 postgres_scanner、Parquet 导出还是 FDW - 选错时最可能出现的两个故障模式 5. 约束:(运维能力、延迟预算、合规要求)
相关页面
- PostgreSQL 血缘与兼容数据库——另一种对比:复用 PostgreSQL 本身的系统
- 云 PostgreSQL 服务版图——选型落在服务器上时的托管选项
- PostgreSQL 扩展生态——“选 PostgreSQL”所包含的 pgvector、PostGIS 等
- RAG 管道——PostgreSQL 承担的在线检索路径
Last updated on