用 Pandas 处理10GB数据,加载就要5分钟。
换成 DuckDB,同样的查询,3秒出结果。
不是你的代码写得慢,是工具选错了。
下面这6个技巧,是我用 DuckDB 三个月总结出来的。
1. 直接查询 CSV,不用加载到内存
Pandas 的做法:
import pandas as pd
df = pd.read_csv("huge_file.csv") # 10GB 文件,直接爆内存
DuckDB 的做法:
import duckdb
# 直接查询 CSV 文件,不加载到内存
result = duckdb.query("""
SELECT city, AVG(price) as avg_price
FROM 'sales.csv'
GROUP BY city
ORDER BY avg_price DESC
""").df()
文件再大也没关系。DuckDB 用列式存储,只读需要的列。
实测:5GB 的 CSV 文件,Pandas 需要 8GB 内存,DuckDB 只要 200MB。
2. 并行查询利用多核 CPU
Pandas 是单线程的。你的8核 CPU,Pandas 只用了1个核。
DuckDB 默认开启并行查询。
import duckdb
# 自动并行执行
result = duckdb.query("""
SELECT
date_trunc('month', order_date) as month,
category,
SUM(amount) as total
FROM 'orders.csv'
GROUP BY month, category
ORDER BY month, total DESC
""").df()
查询过程中,DuckDB 会自动分配多个线程并行执行。
实测:同样的查询,DuckDB 比 Pandas 快 8-10 倍。
3. 窗口函数做排行榜
Pandas 做排行榜要写一堆代码。
DuckDB 一条 SQL 搞定。
import duckdb
# 每个城市的销售额 Top3 商品
result = duckdb.query("""
SELECT *
FROM (
SELECT
city,
product,
sales,
ROW_NUMBER() OVER (PARTITION BY city ORDER BY sales DESC) as rank
FROM 'sales_data.csv'
) t
WHERE rank <= 3
""").df()
输出:
| city | product | sales | rank |
|---|---|---|---|
| 北京 | iPhone 15 | 50000 | 1 |
| 北京 | MacBook Pro | 45000 | 2 |
| 北京 | AirPods | 30000 | 3 |
| 上海 | iPhone 15 | 48000 | 1 |
| … | … | … | … |
不用写 groupby、sort、head,一行 SQL 解决。
4. 处理嵌套 JSON 数据
现实中的数据经常是嵌套的。Pandas 处理起来很麻烦。
DuckDB 原生支持 JSON 查询。
import duckdb
# 查询嵌套 JSON
result = duckdb.query("""
SELECT
user_id,
data->>'name' as username,
data->'orders'->0->>'product' as first_order_product,
array_length(data->'orders') as order_count
FROM 'users.json'
LIMIT 10
""").df()
->> 提取字符串,-> 提取对象,array_length 获取数组长度。
不用再手动解析 JSON,不用写循环提取。
5. 直接读 Parquet 文件
Parquet 是数据分析的最佳格式。列式存储,压缩率高,读取快。
DuckDB 可以直接读 Parquet,不用转换。
import duckdb
# 直接查询 Parquet
result = duckdb.query("""
SELECT
category,
AVG(price) as avg_price,
COUNT(*) as count
FROM 'data.parquet'
WHERE date >= '2024-01-01'
GROUP BY category
ORDER BY avg_price DESC
""").df()
而且 DuckDB 支持 Parquet 的谓词下推——只读取需要的列和数据块。
实测:10GB 的 Parquet 文件,查询 100MB 的数据,DuckDB 只需 2 秒。
6. 创建视图复用查询逻辑
复杂的查询可以做成视图,方便复用。
import duckdb
# 创建视图
duckdb.execute("""
CREATE VIEW sales_summary AS
SELECT
city,
category,
SUM(amount) as total_sales,
COUNT(*) as order_count,
AVG(amount) as avg_order_value
FROM 'sales_data.csv'
GROUP BY city, category
""")
# 查询视图
result = duckdb.query("""
SELECT *
FROM sales_summary
WHERE total_sales > 100000
ORDER BY total_sales DESC
""").df()
视图不需要保存数据,每次查询时实时计算。
可以像查表一样查视图,代码更简洁。
什么时候用 Pandas,什么时候用 DuckDB
| 场景 | 推荐工具 |
|---|---|
| 数据量 < 1GB,简单分析 | Pandas |
| 数据量 > 1GB,复杂查询 | DuckDB |
| 需要交互式探索 | Pandas + Jupyter |
| 需要生产环境部署 | DuckDB |
| 嵌套 JSON 处理 | DuckDB |
| 实时报表生成 | DuckDB |
总结
DuckDB 不是要取代 Pandas,而是补足它的短板。
数据处理流程可以这样:
- 用 DuckDB 查询大数据,筛选出需要的子集
- 把结果导入 Pandas 做可视化
- 或者直接导出 CSV/Parquet 给下游使用
你现在的分析流程是什么样的?有没有被大数据拖慢过?