Polars 性能碾压 Pandas 吗?千万级真实业务数据实测给出答案

简介: Polars 性能碾压 Pandas 吗?千万级真实业务数据实测给出答案

围绕 Polars 最常见的说法是"比 Pandas 快 10~30 倍"。这个数字在官方 benchmark 和社区博客里反复出现,但对于一线业务开发者,真正需要回答的问题有三个:在我自己的数据规模上到底快多少?优势集中在哪些操作?迁移的工程代价值不值?
本文用一份千万行真实业务数据,在严格控制变量的条件下实测载入、过滤、分组聚合、Join、排序五大核心操作,并给出迁移决策框架。
一、两位选手的架构差异
性能差距的根源不在代码层面,而在底层架构选型。
维度
Pandas 2.2
Polars 0.20
底层实现
C + Cython
Rust
执行模型
单线程(GIL 限制)
多线程并行(Rayon 调度器)
内存格式
NumPy ndarray
Apache Arrow(列式、零拷贝)
执行模式
Eager(立即执行)
Eager + Lazy(惰性查询优化)
Lazy 优化能力

谓词下推、投影裁剪、并行哈希
三句话概括差异:Pandas 的每一步操作是单线程立即执行,Polars 是多线程并行执行;Pandas 读完 CSV 还要做一次内存格式转换,Polars 基于 Arrow 零拷贝直接可用;Polars 的 Lazy API 能在执行前看到完整查询计划,做全局优化。这些架构差异决定了后面的实测数字。
二、测试环境与数据
```硬件: 8 核 16G 服务器
Python: 3.12.1
Pandas: 2.2.0
Polars: 0.20.15
数据量: 1000 万行 × 12 列(CSV 文件 567 MB)


数据生成
```import pandas as pd
import numpy as np
import polars as pl
import time

np.random.seed(42)
N = 10_000_000

df_source = pd.DataFrame({
    'order_id':   range(N),
    'user_id':    np.random.randint(1, 500_000, N),
    'product_id': np.random.randint(1, 10_000, N),
    'amount':     np.random.uniform(10, 5000, N).round(2),
    'quantity':   np.random.randint(1, 50, N),
    'region':     np.random.choice(['华东', '华南', '华北', '西南', '东北'], N),
    'category':   np.random.choice(['电子', '服装', '食品', '家居', '图书'], N),
    'status':     np.random.choice(['paid', 'pending', 'refunded', 'shipped'], N),
    'channel':    np.random.choice(['app', 'web', 'mini_program'], N),
    'order_date': pd.date_range('2023-01-01', periods=N, freq='s'),
})

df_source.to_csv('orders_10m.csv', index=False)

计时工具
```def benchmark(func, args, repeat=3, **kwargs):
"""执行多次取最优值,减少系统调度波动"""
times = []
for _ in range(repeat):
start = time.perf_counter()
result = func(
args, **kwargs)
times.append(time.perf_counter() - start)
return min(times), result


三、五大核心操作实测
3.1 CSV 载入
```# Pandas
def pandas_read():
    return pd.read_csv('orders_10m.csv',
        dtype={'region': 'category', 'category': 'category', 'status': 'category'},
        parse_dates=['order_date'])

# Polars(默认多线程解析)
def polars_read():
    return pl.read_csv('orders_10m.csv',
        schema_overrides={'order_date': pl.Datetime},
        try_parse_dates=True)

p_time, _ = benchmark(pandas_read)
pl_time, _ = benchmark(polars_read)
print(f"Pandas: {p_time:.2f}s | Polars: {pl_time:.2f}s | 加速比: {p_time/pl_time:.1f}x")

实测结果:

耗时
内存峰值
Pandas
12.40s
1.8 GB
Polars
2.10s
0.9 GB
差距的原因是双重的:Polars 用多线程并行解析 CSV 文件(8 核同时读取不同 chunk),且基于 Arrow 列式格式,解析完成后无需从 NumPy 数组做内存转换。Pandas 单线程读取完后,还要将 object 列逐个转换为 category,额外消耗了 6~8 秒。
3.2 数据过滤
```# Pandas:筛选金额 >1000 且华东地区的已付款订单
def pandas_filter(df):
return df[(df['amount'] > 1000) & (df['region'] == '华东') & (df['status'] == 'paid')]

Polars Eager

def polars_filter(df):
return df.filter(
(pl.col('amount') > 1000) &
(pl.col('region') == '华东') &
(pl.col('status') == 'paid'))

Polars Lazy(惰性执行,可优化查询计划)

def polars_lazy_filter(lf):
return lf.filter(
(pl.col('amount') > 1000) &
(pl.col('region') == '华东') &
(pl.col('status') == 'paid')).collect()


实测结果:
方案
耗时
Pandas
0.38s
Polars Eager
0.09s
Polars Lazy
0.07s
过滤是纯 CPU 操作,将千万行数据均分到 8 个线程并行扫描,Pandas 单线程遍历需要 0.38 秒,Polars 8 核并行降到 0.09 秒。Lazy 模式还能在执行前发现可以提前裁剪的列(这里只需 amount、region、status 三列),减少内存读取量,再快 20%。
3.3 分组聚合
```# Pandas
def pandas_groupby(df):
    return df.groupby(['region', 'category']).agg(
        total_amount=('amount', 'sum'),
        avg_amount=('amount', 'mean'),
        max_amount=('amount', 'max'),
        order_count=('order_id', 'count'),
        unique_users=('user_id', 'nunique'),
    ).reset_index()

# Polars
def polars_groupby(df):
    return df.group_by(['region', 'category']).agg([
        pl.col('amount').sum().alias('total_amount'),
        pl.col('amount').mean().alias('avg_amount'),
        pl.col('amount').max().alias('max_amount'),
        pl.col('order_id').count().alias('order_count'),
        pl.col('user_id').n_unique().alias('unique_users'),
    ])

这是日常分析中最频繁、也最耗时的操作。
实测结果:
方案
耗时
Pandas
1.42s
Polars Eager
0.31s
Polars Lazy
0.22s
分组聚合是 Polars 优势最突出的场景。Pandas 单线程遍历千万行做 hash 分桶,耗时 1.4 秒。Polars 使用并行哈希聚合算法——将数据按 hash 分片到 8 个线程,每个线程独立构建局部哈希表,最后合并结果。Lazy 模式还能合并多个聚合操作到单次遍历中。
3.4 Join 合并
```# 右表:产品维度表 1 万行
products = pd.DataFrame({
'product_id': range(1, 10_001),
'productname': [f'商品{i}' for i in range(1, 10_001)],
'brand': np.random.choice(['品牌A', '品牌B', '品牌C'], 10000),
})
products.to_csv('products.csv', index=False)

Pandas

def pandas_join(orders, products):
return pd.merge(orders, products, on='product_id', how='left')

Polars

def polars_join(orders_pl, products_pl):
return orders_pl.join(products_pl, on='product_id', how='left')


实测结果:
方案
耗时
Pandas
3.85s
Polars
0.52s
Join 是 Pandas 的传统痛点。pd.merge 在千万级数据上做哈希连接时,单线程构建哈希表 + 单线程探测匹配,耗时接近 4 秒。Polars 使用并行哈希连接——将左表按 product_id 的 hash 值分片,每个线程处理一片,与右表的哈希表做局部匹配后合并。
3.5 排序
```# Pandas
def pandas_sort(df):
    return df.sort_values(['region', 'amount'], ascending=[True, False])

# Polars
def polars_sort(df):
    return df.sort(['region', 'amount'], descending=[False, True])

实测结果:
方案
耗时
Pandas
4.67s
Polars
0.85s
排序是千万行数据上的性能重灾区。Pandas 依赖 NumPy 的单线程快速排序,在多列排序场景下需要多次分区遍历。Polars 使用并行归并排序——将数据分片排序后多路归并。
四、汇总:全景性能对比
操作
Pandas
Polars Eager
Polars Lazy
加速比
CSV 载入
12.40s
2.10s

5.9x
过滤
0.38s
0.09s
0.07s
5.4x
分组聚合
1.42s
0.31s
0.22s
6.5x
Join 合并
3.85s
0.52s

7.4x
排序
4.67s
0.85s

5.5x
全链路
22.72s
3.87s

5.9x
核心结论:千万级数据规模下,Polars 在所有核心操作上均有 5~7 倍的加速。优势集中在三类操作——Join(并行哈希)、分组聚合(并行哈希分桶)、排序(并行归并)。数据量越大,并行收益越显著。
五、公平修正:Pandas + PyArrow 后端
Pandas 2.0 引入了 PyArrow 后端,部分缩小了差距。补上这组数据:
操作
Pandas 原生
Pandas + PyArrow
Polars
CSV 载入
12.40s
3.21s
2.10s
分组聚合
1.42s
0.89s
0.31s
Join 合并
3.85s
1.95s
0.52s
PyArrow 后端让 Pandas 在 CSV 载入上追近 Polars(差距从 6 倍缩小到 1.5 倍),但在分组聚合和 Join 上仍有 3~4 倍差距。单线程架构的计算瓶颈无法被内存格式优化弥补。
六、迁移成本评估
性能数字只是决策的一个维度。迁移到 Polars 意味着 API 重写和生态适配。
6.1 API 差异核心对照
操作
Pandas
Polars
新增列
df['c'] = df['a'] + df['b']
df.with_columns((pl.col('a') + pl.col('b')).alias('c'))
条件赋值
np.where(df['a']>0, 'Y', 'N')
pl.when(pl.col('a')>0).then('Y').otherwise('N')
分组聚合
df.groupby('a').agg({'b':'sum'})
df.group_by('a').agg(pl.col('b').sum())
Merge
pd.merge(df1, df2, on='key')
df1.join(df2, on='key')
链式空值填充
df['a'].fillna(0)
df.with_columns(pl.col('a').fill_null(0))
6.2 迁移决策矩阵
条件
建议
数据量 < 100 万行
Pandas 够用,迁移收益有限
数据量 100 万~1000 万行
推荐迁移,单操作快 3~5 倍
数据量 > 1000 万行
必须迁移,Pandas 已无法胜任
Join / GroupBy 是主要瓶颈
优先迁移这两类操作
重度依赖 scikit-learn / statsmodels
渐进迁移,分析阶段用 Polars,ML 阶段 to_pandas()
转换
存量 Pandas 代码 > 5000 行
新模块用 Polars,旧模块按需重构
6.3 渐进迁移策略
to_pandas() 在底层使用 Arrow 零拷贝机制,转换耗时在毫秒级,不构成性能瓶颈。
七、完整数据链路的性能优化
在企业场景中,性能瓶颈不仅在分析阶段,也在数据采集阶段。原始数据通过 API 或爬虫从外部获取时,采集效率直接影响分析的时效性。
```import requests
import polars as pl
from io import StringIO

通过亿牛云 API 代理获取出口 IP,避免单 IP 被限流

api_url = "http://ip.16yun.cn:817/myip/pl//?s=&u=&format=json"
proxy_info = requests.get(api_url, timeout=10).json()[0]
proxy = f"http://{proxy_info['ip']}:{proxy_info['port']}"

采集数据(返回 403 检查白名单,返回 429 降低频率)

resp = requests.get("https://api.example.com/export",
proxies={"http": proxy, "https": proxy}, timeout=30)

直接从内存字符串载入 Polars,跳过文件落盘

df = pl.read_csv(StringIO(resp.text), try_parse_dates=True)

Polars Lazy 链式分析

result = (df.lazy()
.filter(pl.col('amount') > 100)
.group_by('region')
.agg(pl.col('amount').sum().alias('revenue'))
.collect()
)
```

这条链路的优化点是:代理 IP 保证采集不被限流,read_csv(StringIO) 省去文件 I/O,Polars Lazy 引擎在 collect() 时才触发执行并做全局优化。相比"采集 → 存 CSV → Pandas 读取 → 分析"的传统链路,整体耗时减少 60% 以上。
八、最终判断
基于实测数据,迁移决策可以拆成三个层次:
第一层:看数据规模
数据量
推荐方案
< 10 万行
Pandas,迁移无意义
10 万~500 万行
Pandas + PyArrow 后端
500 万~5000 万行
Polars(单机最优解)

5000 万行
Polars Lazy + DuckDB
第二层:看瓶颈操作
如果业务中高频使用 Join 和 GroupBy,迁移收益最大——这两个操作 Polars 快 6~7 倍。如果主要是列选择和简单过滤,差距不到 3 倍,迁移必要性不大。
第三层:看生态依赖
重度依赖 scikit-learn、statsmodels、Matplotlib 的项目,最终仍需转回 Pandas。但 to_pandas() 的零拷贝转换耗时在毫秒级,不构成实质障碍。
"Polars 碾压 Pandas"这个说法在千万级数据 + 计算密集型操作的条件下成立,在十万级数据 + 简单过滤的场景下不成立。选型的正确姿势是:先用你的真实数据跑一遍 benchmark,再基于实测数字做决策,而不是被社区营销数字牵着走。

相关文章
|
10天前
|
人工智能 JSON 自然语言处理
让教学更智慧:用阿里云百炼工作流,自动生成中小学教材内容#小有可为#有温度的AI
通过可视化工作流编排,将大模型推理能力转化为标准化的教学内容生成引擎。教师只需输入教材标题和适用学段,即可自动获得结构完整、符合课程标准的章节内容,大幅降低备课门槛,助力教育资源均衡化。
486 126
|
19天前
|
Linux 程序员 数据格式
【2026最新】Notepad++下载、安装和使用一篇搞定(附中文版安装包)
Notepad++ 是一款免费开源、轻量高效的 Windows 文本编辑器,支持 C/Python/HTML 等 80+ 语言语法高亮、代码折叠、正则替换、编码转换及插件扩展,专为程序员与文本处理用户打造,完美替代系统记事本。(239字)
|
5天前
|
人工智能 缓存 安全
Claude Code 封号真实原因曝光,这次彻底不装了,直接针对国内开发者的账号下手?
Claude Code 封号潮背后:逆向扒出客户端隐写区域标记,Anthropic 政策收紧叠加 DeepSeek 7 月涨价,国产替代更紧迫。
|
6天前
|
人工智能 安全 Cloud Native
Higress 新发布:AI Gateway 能力增强,Gateway API 及其推理扩展持续打磨
增强 AI 网关能力,持续打磨 Gateway API 及其推理扩展。
347 124
|
5天前
|
人工智能 安全 程序员
终于,Claude Code 封号的原因被曝光了!竟然针对中国用户,植入隐形代码?!
通俗易懂地揭秘 Claude Code 封号的手段,分享一些自己对 AI 编程困境的思考,Codex、Cursor、DeepSeek、智谱 GLM、甚至是豆包,都有所行动了
347 1
|
14天前
|
机器学习/深度学习 人工智能 调度
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
HappyHorse 1.1 是新一代视频生成大模型,全面升级动态表现力、角色一致性、指令遵循、视觉质感与音画协同能力。支持I2V/T2V/R2V三类生成,适配短剧、电商广告、品牌营销等场景,提供高质、流畅、可控的AI视频生产力。
844 5
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
|
12天前
|
人工智能 定位技术 SEO
我学 GEO 第 15 天:终于知道AI GEO该如何做?
我是暴走的莉莉酱,边旅行边研究AI GEO的数字游民。专注普通人如何提升“AI可见度”——让AI在回答用户问题时准确识别、理解并推荐你。不讲玄学,只做可测、可调、可持续的GEO实践。
469 127