pg_duckdb: DuckDB 官方的 PostgreSQL 扩展

John Doe 十一月 20, 2025

pg_duckdb 将 DuckDB 的列式向量分析引擎集成到 PostgreSQL 中,可支持高性能分析和数据密集型应用。

image

核心功能

  • 无需修改即可执行分析查询:像往常一样运行现有的 SQL 分析查询,当你设置duckdb.force_execution=true时,pg_duckdb 会自动使用 DuckDB 的 SQL 引擎执行这些查询。
  • 读写数据湖中的数据:可从 S3、GCS、Azure 和 R2 存储服务中读取和写入 Parquet、CSV、JSON、Iceberg 和 Delta Lake 格式的数据。

pg_duckdb 工作原理

pg_duckdb 会自动加速你现有的分析查询,具体体现在以下两点:

  1. 无需特殊语法:对于常规 PostgreSQL 表的查询,无需修改 SQL 语句。像往常一样运行 SELECT 语句,pg_duckdb 会自动使用 DuckDB 引擎执行。
  2. 无需导出数据:无需将数据导出为 Parquet 或其他格式,pg_duckdb 可直接作用于现有的 PostgreSQL 表。

实际应用示例

查询现有 PostgreSQL 数据

这是最常见、最直接的使用场景。若你有一个标准 PostgreSQL 表,可通过标准 SQL 对其进行查询。

假设你有一个名为orders的 PostgreSQL 表,如下:

-- 标准 PostgreSQL 表
CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    product_name TEXT,
    amount NUMERIC,
    order_date DATE
);

INSERT INTO orders (product_name, amount, order_date)
VALUES ('Laptop', 1200.00, '2024-07-01'),
       ('Keyboard', 75.50, '2024-07-01'),
       ('Mouse', 25.00, '2024-07-02');

要运行分析查询,只需编写标准 SQL 并配置duckdb.force_execution,后续操作由 pg_duckdb 自动完成。

SET duckdb.force_execution = true;
SELECT
    order_date,
    COUNT(*) AS number_of_orders,  -- 订单数量
    SUM(amount) AS total_revenue   -- 总营收
FROM
    orders
GROUP BY
    order_date
ORDER BY
    order_date;

查询外部数据

pg_duckdb 允许你将外部文件(如 Parquet 或 CSV)当作数据库中的表进行查询,非常适合通过 pg_duckdb 查询数据湖。

-- 直接通过 SQL 在几秒内配置 S3 访问权限
SELECT duckdb.create_simple_secret(
    type := 'S3', key_id := 'your_key', secret := 'your_secret', region := 'us-east-1'
);

SELECT
    r['product_name'],  -- 'r' 用于遍历 read_parquet() 返回的行对象
    AVG(r['rating']) AS average_rating  -- 平均评分
FROM
    read_parquet('s3://your-bucket/reviews.parquet') r
GROUP BY
    r['product_name']
ORDER BY
    average_rating DESC;

关联 PostgreSQL 与 DuckDB 数据

你可轻松将 PostgreSQL 表与数据湖中的外部数据进行关联查询。

-- 将 PostgreSQL 表与远程 Parquet 文件关联
SELECT
    o.product_name,    -- 产品名称
    o.total_revenue,   -- 产品总营收
    r.average_rating   -- 产品平均评分
FROM
    (
        -- 第一步:聚合本地 orders 表数据
        SELECT
            product_name,
            SUM(amount) AS total_revenue
        FROM
            orders
        GROUP BY
            product_name
    ) o
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  -- 按产品名称关联
ORDER BY
    o.total_revenue DESC;

现代数据湖格式支持

pg_duckdb 支持处理 DuckLake、Iceberg 和 Delta Lake 等现代数据格式。

-- 带时间旅行功能的 Apache Iceberg 表查询
SELECT duckdb.install_extension('iceberg');  -- 安装 Iceberg 扩展

-- 查询指定快照版本的 Iceberg 表
SELECT * FROM iceberg_scan('s3://warehouse/sales_iceberg', version := '2024-03-15-snapshot');

-- 处理支持 schema 演进的 Delta Lake
SELECT duckdb.install_extension('delta');  -- 安装 Delta 扩展
SELECT * FROM delta_scan('s3://lakehouse/user_events')  -- 查询 Delta Lake 表

参考

pg_duckdb:https://github.com/duckdb/pg_duckdb