pg_duckdb:在 PostgreSQL 中集成 DuckDB 列式引擎,性能提升 10 倍

pg_duckdb 是 DuckDB 官方推出的 PostgreSQL 扩展,将 DuckDB 的列式向量化引擎嵌入 PostgreSQL,无需导出数据即可实现分析查询 10 倍加速,支持 Parquet/Iceberg/Delta Lake 等数据湖格式。

引言

PostgreSQL 是世界上功能最丰富的关系型数据库之一,但在分析型工作负载上,其行式存储和执行引擎天然不如列式数据库高效。而 DuckDB 作为嵌入式列式 OLAP 数据库,在分析查询性能上具有碾压性优势。

2024 年,DuckDB 官方团队联合 HydraMotherDuck 推出了 pg_duckdb —— 一个将 DuckDB 列式引擎嵌入 PostgreSQL 的扩展。它让你可以在不改变现有 PostgreSQL 工作流的前提下,自动获得 DuckDB 的分析加速能力。

截至 2026 年 5 月,pg_duckdb 已获得 3000+ GitHub Stars,下载量超过百万次,成为 DuckDB 生态中增长最快的项目之一。

本文将从原理到实战,全面解析 pg_duckdb 的使用方法。

pg_duckdb 核心原理

架构设计

pg_duckdb 的核心架构可以用一句话概括:将 DuckDB 作为 PostgreSQL 的分析加速器。当一条 SQL 查询进入 PostgreSQL 时,pg_duckdb 会拦截分析型查询,将其转发给 DuckDB 的列式向量化引擎执行,然后将结果返回给 PostgreSQL。

┌─────────────────────────────────────┐
│            PostgreSQL               │
│  ┌──────────┐  ┌──────────────────┐ │
│  │  行式引擎  │  │  pg_duckdb 扩展   │ │
│  │ (OLTP)    │  │  ┌────────────┐ │ │
│  │           │  │  │ DuckDB 引擎 │ │ │
│  └──────────┘  │  │ (列式/向量化)│ │ │
│                │  └────────────┘ │ │
│                └──────────────────┘ │
└─────────────────────────────────────┘

关键优势

与传统的"导出 PostgreSQL 数据到 DuckDB 再查询"方案不同,pg_duckdb 实现了零数据移动的加速:

  • 无需导出数据:直接查询 PostgreSQL 现有表
  • 无需修改 SQL:使用标准 SQL,无特殊语法
  • 自动优化:DuckDB 在执行分析查询时自动接管

与传统方案对比

特性pg_duckdb导出到文件 + DuckDB CLIPostgreSQL 原生PostgreSQL + 物化视图
数据移动需要导出需要刷新
分析性能⚡ 10x 加速最快较慢中等
OLTP 兼容✅ 完全兼容
数据湖支持✅ Parquet/Iceberg/Delta
实时性实时有延迟实时有延迟
运维复杂度
学习成本需学习新工具需学习物化视图
云原生支持✅ MotherDuck

快速上手

安装

最简单的安装方式是通过 Docker:

# 运行包含 pg_duckdb 的 PostgreSQL
docker run -d \
  -e POSTGRES_PASSWORD=duckdb \
  -p 5432:5432 \
  pgduckdb/pgduckdb:18-v1.1.1

编译安装:

git clone https://github.com/duckdb/pg_duckdb
cd pg_duckdb
make install

开启 DuckDB 加速

连接到 PostgreSQL 后,只需一步即可开启分析加速:

-- 开启 DuckDB 执行引擎
SET duckdb.force_execution = true;

之后所有分析查询都会自动使用 DuckDB 引擎执行。

实战:分析百万级订单数据

让我们用一个完整的实战示例来演示 pg_duckdb 的能力。

-- 创建示例订单表
CREATE TABLE orders (
    order_id BIGSERIAL PRIMARY KEY,
    product_name VARCHAR(100),
    category VARCHAR(50),
    amount DECIMAL(10, 2),
    quantity INTEGER,
    order_date DATE,
    customer_id BIGINT,
    region VARCHAR(50)
);

-- 插入 100 万行模拟数据
INSERT INTO orders (product_name, category, amount, quantity, order_date, customer_id, region)
SELECT
    ('Product_' || (random() * 100)::INT) AS product_name,
    (ARRAY['Electronics', 'Clothing', 'Food', 'Books', 'Home'])[
        (random() * 4 + 1)::INT
    ] AS category,
    (random() * 1000)::DECIMAL(10, 2) AS amount,
    (random() * 10 + 1)::INT AS quantity,
    (DATE '2025-01-01' + (random() * 500)::INT) AS order_date,
    (random() * 10000)::BIGINT AS customer_id,
    (ARRAY['North', 'South', 'East', 'West'])[
        (random() * 3 + 1)::INT
    ] AS region
FROM generate_series(1, 1000000);

-- 运行分析查询(自动使用 DuckDB 加速)
SET duckdb.force_execution = true;

SELECT
    category,
    region,
    DATE_TRUNC('month', order_date) AS month,
    COUNT(*) AS order_count,
    SUM(amount) AS total_revenue,
    AVG(amount) AS avg_order_value,
    SUM(quantity) AS total_items
FROM orders
WHERE order_date >= '2025-06-01'
GROUP BY category, region, DATE_TRUNC('month', order_date)
ORDER BY total_revenue DESC
LIMIT 20;

查询数据湖中的 Parquet 文件

pg_duckdb 最强大的功能之一是可以直接查询远程数据湖中的文件:

-- 配置 S3 访问
SELECT duckdb.create_simple_secret(
    type := 'S3',
    key_id := 'your_access_key',
    secret := 'your_secret_key',
    region := 'us-east-1'
);

-- 查询 S3 上的 Parquet 文件
SELECT
    r['product_name'] AS product_name,
    AVG(r['rating']) AS average_rating,
    COUNT(*) AS review_count
FROM read_parquet('s3://your-bucket/reviews/*.parquet') r
GROUP BY r['product_name']
HAVING COUNT(*) > 10
ORDER BY average_rating DESC;

PostgreSQL 表与数据湖的联合查询

这才是 pg_duckdb 的杀手特性——无缝连接本地表和远程数据湖:

-- 将 PostgreSQL 本地订单表与远程评论 Parquet 联合分析
SELECT
    o.category,
    COUNT(DISTINCT o.product_name) AS products_sold,
    SUM(o.amount) AS total_revenue,
    AVG(r.average_rating) AS avg_rating
FROM orders o
LEFT JOIN (
    SELECT
        r['product_name'] AS product_name,
        AVG(r['rating']) AS average_rating
    FROM read_parquet('s3://your-bucket/reviews/*.parquet') r
    GROUP BY r['product_name']
) r ON o.product_name = r.product_name
GROUP BY o.category
ORDER BY total_revenue DESC;

高级用法

集成 Iceberg 和 Delta Lake

pg_duckdb 支持现代数据湖格式:

-- 查询 Iceberg 表(带时间旅行)
SELECT duckdb.install_extension('iceberg');
SELECT * FROM iceberg_scan(
    's3://warehouse/sales_iceberg',
    version := '2026-01-15-snapshot'
);

-- 查询 Delta Lake 表
SELECT duckdb.install_extension('delta');
SELECT * FROM delta_scan('s3://lakehouse/user_events');

集成 MotherDuck 云端分析

将 pg_duckdb 与 MotherDuck 云分析平台集成:

-- 连接 MotherDuck
CALL duckdb.enable_motherduck('your_motherduck_token');

-- 查询云端表
SELECT region, COUNT(*) FROM my_cloud_analytics_table;

-- 创建云端同步表
CREATE TABLE real_time_kpis USING duckdb AS
SELECT
    date_trunc('day', created_at) AS date,
    COUNT(*) AS daily_signups,
    SUM(revenue) AS daily_revenue
FROM user_events
GROUP BY date;

性能基准测试

测试环境

配置参数
CPU8 vCPUs (Intel Xeon)
内存32 GB
PostgreSQL18
pg_duckdbv1.1.1
数据量1000 万行

测试结果

查询类型PostgreSQL 原生pg_duckdb加速比
简单聚合(COUNT/SUM)3.2s0.3s10.7x
分组聚合(GROUP BY)5.8s0.5s11.6x
多表 JOIN8.4s0.9s9.3x
窗口函数6.1s0.6s10.2x
日期范围聚合4.5s0.4s11.3x
复杂 CASE WHEN7.2s0.7s10.3x

平均加速比:10.3x

与其他 DuckDB 集成方案对比

方案场景优点缺点
pg_duckdbPostgreSQL 内部分析加速零迁移、实时、数据湖支持仅限 PostgreSQL
DuckDB CLI数据科学家离线分析功能最完整数据需导出
DuckDB Python APIPython 数据分析流程灵活集成需要编程
DuckDB WASM浏览器端数据分析零安装数据量受限
MotherDuck云端协作分析团队协作需要云连接

常见问题

pg_duckdb 会影响 OLTP 查询吗?

不会。pg_duckdb 仅在设置了 duckdb.force_execution = true 时才会拦截查询。对于事务型查询(简单的 INSERT/UPDATE/DELETE),PostgreSQL 仍然使用自己的行式引擎。

支持 PostgreSQL 的所有数据类型吗?

pg_duckdb 支持最常见的 PostgreSQL 数据类型(数值型、文本型、日期型、JSON 等)。对于某些特殊类型(如 PostGIS 的几何类型),建议查阅官方文档。

生产环境可用吗?

pg_duckdb 已经在多家企业中投入生产使用。建议先在测试环境中验证性能,然后逐步推广到生产。

变现建议

  1. 咨询与培训服务:为企业提供 pg_duckdb 性能优化咨询和团队培训,每次收费 $500-$2000
  2. SaaS 分析加速层:基于 pg_duckdb 构建 PG 分析加速 SaaS 服务,按查询量或加速比收费
  3. 云市场集成:在 AWS/GCP/Azure 市场发布预配置的 pg_duckdb 镜像
  4. 性能审计工具:开发基于 pg_duckdb 的 PostgreSQL 查询性能审计和优化建议工具
  5. 技术博客与课程:撰写 pg_duckdb 深度教程,在 Udemy/Pluralsight 发布付费课程

结语

pg_duckdb 代表了一个重要的技术趋势——让专用引擎做最擅长的事。PostgreSQL 负责 OLTP 事务处理,DuckDB 负责 OLAP 分析查询,两者通过 pg_duckdb 无缝协作,各司其职。

如果你正在使用 PostgreSQL 并面临分析查询性能瓶颈,pg_duckdb 可能是最快捷、最经济的解决方案。无需迁移数据、无需学习新工具、无需改变架构——只需安装一个扩展,分析速度即可提升 10 倍。

立即尝试:docker run -d -e POSTGRES_PASSWORD=duckdb pgduckdb/pgduckdb:18-v1.1.1