DuckDB 实战笔记 - 2026-09-09
🔧 周三·工具链搭建 DuckDB 多文件 ETL:一次读 100 个 CSV,比 pandas 快 8 倍
🎯 真实场景
你的业务系统每天导出一个 CSV,一个月后文件夹里堆着 30+ 个文件:sales_2026-08-01.csv、sales_2026-08-02.csv……你想把它们合并分析,用 pandas 要写循环、内存爆掉,DuckDB 一行 glob 搞定。
🐍 代码:Python 一键 ETL
import duckdb
# 1. 直接 glob 读所有文件(自动合并 schema)
con = duckdb.connect()
df = con.execute("
SELECT * FROM read_csv_auto('sales_*.csv')
").fetchdf()
# 2. 清洗 + 聚合一条链写完
result = con.execute("
SELECT
date_trunc('week', date) as week,
SUM(amount) as weekly_sales,
COUNT(DISTINCT customer_id) as buyers
FROM df
WHERE amount > 0
GROUP BY week
ORDER BY week
").fetchdf()
print(result)
💡 核心价值:为什么是 DuckDB?
- glob 原生支持:
read_csv_auto(‘sales_*.csv’)自动发现所有匹配文件,不用手动 list + 拼接 - 自动类型推断:每个文件 schema 略有不同?DuckDB 自动对齐,pandas 得自己 merge dtypes
- 懒执行:所有过滤、聚合在读取时流水线完成,
WHERE amount > 0边读边筛,内存占用极低 - 比 pandas 快 5-10 倍:多线程并行读文件,列式计算,万行数据差距不明显,百万行以上踩压
⚡ 进阶:增量管道 只处理新增文件,不重跑历史:
# 记录上次处理的时间戳
last_run = con.execute("SELECT MAX(processed_at) FROM etl_log").fetchone()[0]
# 只读新增的文件(按文件名日期判断)
new_files = [f for f in glob.glob('sales_*.csv')
if f.split('_')[1] > last_run]
if new_files:
con.execute("
INSERT INTO daily_summary
SELECT * FROM read_csv_auto(?)
", [new_files])
con.execute("INSERT INTO etl_log VALUES (now())")
把这段脚本加进 crontab,每天凌晨自动跑,醒来就有最新报表。🚀