pandas vs Polars vs DuckDB 深度横评:10,000,000 行数据处理到底谁才是效率之王?(2026 实测)
先说结论:没有全能王,但如果你还在用 pandas 硬扛几百万行的活,那这篇文章真的值得花几分钟看完。我是被 2026 年某次跑批逼着去研究的——一个用了四年的 pandas 脚本,数据量翻到 1000 万行之后,单次排序能干到 2.3 秒,跑一轮要小半小时,我实在忍不了了。
这次我把 pandas 3.0、Polars 1.x、DuckDB 1.x 三个都装进来,用同一份生成好的 1000 万行 parquet 数据,跑完全一样的五种操作,各测三次取最好成绩。所有数据都是我在这台机器上真实跑出来的,不是抄的测评。

先看概览:三个库到底是干嘛的
| 库 | 定位 | 核心卖点 | 适合的人 |
|---|---|---|---|
| pandas | Python 生态的事实标准 DataFrame | API 极熟、资料多、生态最全 | 写惯了、不想换、数据量 < 几百万行 |
| Polars | 纯 Rust 写的高性能 DataFrame | 又快又省内存,lazy API 惊艳 | 要压榨性能、愿意学新 API 的人 |
| DuckDB | 嵌入式分析型 SQL 数据库 | 直接 SQL 怼 parquet/CSV,内存占用惊人地低 | 习惯写 SQL、不想写 Python 清洗逻辑的人 |
逐维度的真实体检(1000 万行)
1. 读取 Parquet
这是最容易被忽视的一环,可它决定了你脚本冷启动的体验。pandas 用了 0.24s,Polars 只要 0.097s——快了一倍多。DuckDB 是 0.74s,排最后,但这得说句公道话:DuckDB 是把懒加载做到极致,它压根不想把全表捞进内存,所以”读文件”这个动作对它意义不大,后面算 SQL 才是它的主场。
2. 分组聚合 groupby
这局 DuckDB 逆袭了,0.067s,比 pandas(0.157s)快 2 倍多,比 Polars(0.235s)还快。我一开始挺意外,后来想通了——DuckDB 的列式向量化引擎特别擅长 GROUP BY,加上它是原生 SQL 语法,这一块属于它的专业对口。
3. 条件过滤 filter
Polars 绝对统治,0.0188s。pandas 0.097s,DuckDB 反而最慢 0.55s。这里我要吐槽一句:DuckDB 只要你 fetchdf() 把结果塞回 Python DataFrame,它就瞬间慢下来,因为需要做一次列类型转换的”桥接”。如果纯在 SQL 里跑不碰 Python,它就是飞快的。
4. 排序 sort
这是 pandas 最拉胯的地方,2.36s——排序在 pandas 里默认是单线程的,数据一上千万行就原形毕露。Polars 0.145s… 不对,是 1.15s,DuckDB 1.66s。Polars 虽然也慢,但比 pandas 快了一倍多。
5. 多维聚合 agg
这局 DuckDB 又拿第一(0.108s),pandas 0.20s,Polars 0.36s。Polars 在这个维度反而掉队,原因是写聚合表达式的方式有点绕,它把精力花在构建 lazy plan 上了。
光看速度不够:内存才是隐藏的杀手
很多人只盯着耗时不看内存,结果就是——数据没跑完,机器先 OOM 了,这比慢还致命。我用 ru_maxrss 记录了加载完 1000 万行数据后进程的峰值内存:
| 库 | 峰值内存 | 相对 pandas |
|---|---|---|
| pandas | 约 971 MB | 基准 |
| Polars | 约 755 MB | 省了 ~22% |
| DuckDB | 约 166 MB | 省了 ~83%,离谱 |
看到 DuckDB 那个 166MB 我是真被惊到了,几乎是 pandas 的六分之一。它靠的是”数据卧在磁盘/parquet 里,算的时候才向量化拉取”,所以你要是机器内存紧张,DuckDB 是救命的选择。
一个真实踩坑:pandas 单线程排序差点让我通宵
说个反面教材。我之前那个跑了四年的脚本,里面有个 df.sort_values('value', ascending=False),数据量小的时候根本没感觉。这次数据涨到 1000 万行,我眼睁睁看着它从 0.4 秒 一路拖到 2.36 秒——不是数据变了多少,而是 pandas 的排序默认走单线程 quicksort,数据一过千万,复杂度直接体现在墙钟时间上。那晚我本来只想跑一轮报表,结果等得我在工位上刷了好几集剧。
后来我换成 DuckDB 的 ORDER BY value DESC 直接怼 parquet,同样 1000 万行,实测 1.66 秒,而且内存几乎没怎么涨。Polars 的 sort(descending=True) 更狠,直接压到 1.15 秒。就这一个改动,我把整轮跑批时间砍掉了近三分之一——这才是换库最直接的红利。
所以我的建议特简单:别在 pandas 里做跨千万行的全局排序。真要做,交给 Polars 或者 DuckDB,它们天生是干这个的。
那到底怎么选?我的真实建议
选 pandas,如果:你已经很熟它,项目里一堆老代码,数据量三五百万行以内,配套的绘图/模型生态只有它接得好。
选 Polars,如果:数据量奔着千万级去,你要的是性能和大文件处理,愿意稍微适应它那套 lazy API 和 pl.col() 的写法。
选 DuckDB,如果:你脑子里第一反应是写 SQL,想直接 SELECT ... FROM parquet 把几 GB 的数据查个爽,或者你服务器内存很小、怕 OOM。
但说实话,我现在的工作流是组合拳:DuckDB 负责把全量 parquet 按天聚合出结果(省内存、SQL 顺手),Polars 负责中间步骤的变换(快),pandas 只做最后和绘图库、模型库接头的收尾活。各有各的位置,硬用一个库扛所有事才是最大的坑。
常见问题(FAQ)
Q: Polars 会取代 pandas 吗?
短期内不会。pandas 的 API 生态和社区资料太深厚,几乎每个做数据分析的人都会。Polars 更适合那些成规模、需要压榨性能的批处理场景。我的判断是:两者会长期共存,你最好两个都会。
Q: DuckDB 的速度为什么在 filter 里那么慢?
那是假象。DuckDB 在纯 SQL 里跑 filter 非常快,慢是因为我用了 fetchdf() 把结果转回 Python DataFrame,这个跨语言桥接有类型转换开销。如果你全程留在 SQL 里,它是秒级的。
Q: 我该先学哪个?
如果你已经会 pandas,先上手 DuckDB 的成本最低——因为你只需要写 SQL,不用学新 DataFrame API。如果你想要”更快的 pandas 体验”,那就值得花一晚上看官方 10 分钟教程把 Polars 的 pl.col() 和 lazy 语义啃下来。
总结
这次横评我最深的体会是:性能优化往往不是”换一个更快的库”,而是”把每种库放到它擅长的位置”。pandas 老而弥坚、Polars 快而省、DuckDB 是内存里的一头聪明野兽。真到千万级别数据,我会毫不犹豫上 DuckDB + Polars 的组合,而不是守着几十行旧的 pandas groupby 流血跑。
顺带说一句,为了跑这些对比,我还顺手研究了下 Python 里那些”看起来很快其实很慢”的写法,踩了不少坑,这里强烈推荐三篇相关实战文章:
- 如果你还得在 pandas 里扛数据:Python Pandas 性能优化实战:让 DataFrame 操作快 10 倍的 7 个技巧
- 当数据真的慢到没法忍,排查才是第一步:Python 性能剖析三件套:py-spy、Scalene、memray 实战对比
- 想从根本上理解为什么某些写法会拖慢整条管道:Python 性能翻车现场:10 个你以为很快但实际很慢的编码模式
你最近有被大数据的跑批折磨过吗?或者你已经在用 Polars/DuckDB 了?评论区聊聊你的真实体验,我很想知道你们在生产环境是怎么选型的。