返回首页

DuckDB 作为存储:替换 ETL Postgres

DuckDB 在一个文件中实现紧凑的分析存储,替换 OLAP 任务的 ETL + Postgres。描述架构、更新脚本、SLA 和限制。适合使用 Parquet 数据进行产品分析的开发者。

DuckDB:微型存储取代 ETL 混乱
Advertisement 728x90

DuckDB:轻量级分析数据仓库,取代 ETL 和 Postgres

DuckDB 让你只需一个 .duckdb 文件,就能构建分析数据仓库,无需 ETL 管道和 Postgres 处理 OLAP 工作负载。该引擎可直接处理本地文件或 S3/GCS 中的 Parquet、CSV 和 JSON 文件,为仪表板和报告提供快速数据访问,无需分布式基础设施。非常适合资源有限、注重数据新鲜度和可重复性的团队。

传统 ETL + Postgres 架构的痛点

Postgres 擅长处理 OLTP 工作负载,但 OLAP 查询会引发连锁问题:索引拖慢 vacuum 操作,聚合查询与事务竞争,ETL 任务干扰 schema 变更。团队往往把更多时间花在运维上,而不是分析。DuckDB 作为嵌入式 OLAP 引擎,无需持久化存储,直接消除这些痛点。

架构简化为:

Google AdInline article slot
  • 数据源(数据库、S3、CSV)→ Parquet 快照 → DuckDB(bronze/silver/gold 层)→ BI 导出。

整个管道只需一个定时脚本,包含视图和导出,大幅降低运维负担。

DuckDB 微型数据仓库的 SLA 保障

无需集群复杂性,即可提供清晰 SLA:

  • 数据新鲜度:每 15–60 分钟更新一次,并记录时间戳。
  • 准确性:版本控制的 SQL 视图,结合代码审查。
  • 性能:90 天数据仪表板 p95 < 2 秒。
  • 恢复:从 Parquet 全量重建 <30 分钟。
  • 运维/成本:一个文件 + 一个任务,无持续存储费用。

.duckdb 文件易于备份和迁移。

Google AdInline article slot

产品分析用例

针对 B2B SaaS,事件数据存于关系型数据库,日志存于 S3:

  • 每日表快照转为分区 Parquet。
  • 事件数据转为按日期分区的 Parquet 文件。
  • Gold 层指标视图(周活跃用户、留存队列)。
  • 导出精选 Parquet 供 BI 工具使用。

httpfs 扩展支持直接读取 S3,无需本地拷贝。DuckDB 可将多个 Parquet 文件聚合为单表。

实际实现脚本

更新脚本(Python)

import duckdb
from datetime import datetime

DB = "micro_warehouse.duckdb"

con = duckdb.connect(DB)
con.execute("INSTALL httpfs;")
con.execute("LOAD httpfs;")

con.execute("""
CREATE OR REPLACE VIEW bronze_events AS
SELECT *
FROM read_parquet('data/events/date=*/events-*.parquet');
""")

con.execute("""
CREATE OR REPLACE VIEW silver_events AS
SELECT
  CAST(event_time AS TIMESTAMP) AS event_time,
  user_id,
  team_id,
  event_name,
  NULLIF(properties, '') AS properties
FROM bronze_events
WHERE user_id IS NOT NULL;
""")

con.execute("""
CREATE OR REPLACE VIEW gold_weekly_active_teams AS
SELECT
  date_trunc('week', event_time) AS week,
  COUNT(DISTINCT team_id) AS weekly_active_teams
FROM silver_events
GROUP BY 1
ORDER BY 1;
""")

con.execute("""
COPY (SELECT * FROM gold_weekly_active_teams)
TO 'exports/gold_weekly_active_teams.parquet' (FORMAT PARQUET);
""")

con.execute("CREATE OR REPLACE TABLE ops_refresh_log AS SELECT 1 AS dummy;")
con.execute("""
INSERT INTO ops_refresh_log
SELECT 1
""")

print("Update OK:", datetime.utcnow().isoformat(), "DB:", DB)

此脚本构建 bronze/silver/gold 层并导出指标。

Google AdInline article slot

增量更新

对于 upsert,可基于键(week, team_id)使用 MERGE 到物化表,重新计算滑动窗口。

无中断迁移

保留 Postgres 处理 OLTP,通过 postgres_scanner 扩展读写实时实例,逐步迁移 OLAP 查询,无需重构。

DuckDB 作为数据仓库的局限性

适合:

  • 少数分析师(仪表板、导出)。
  • 仅追加或快照数据。
  • 可移植的 Parquet 流程。

不适合:

  • 高并发交互用户。
  • 带 ACID 保证的 OLTP 写入。
  • 多租户行级安全。
  • 多生产者企业数据契约。

核心要点

  • DuckDB 是单文件嵌入式 OLAP 引擎,直接读取 Parquet/S3。
  • 简化技术栈:脚本 + 视图取代 ETL + Postgres。
  • 可实现 SLA:15 分钟新鲜度,p95<2 秒,<30 分钟恢复。
  • 通过 postgres_scanner 渐进迁移。
  • 局限:低并发,不适合 OLTP。

— Editorial Team

Advertisement 728x90

继续阅读