必须用df.memory_usage(deep=True).sum()才准,因deep=True计入object列中每个Python字符串对象的48字节开销;string[pyarrow]百万行英文城市名约45MB,object则常超200MB。

怎么测字符串内存占用才准?
别只看 df.info() 或 df.memory_usage().sum() 默认输出——它默认不 deep,会漏掉 object 列里每个字符串的 Python 对象开销。必须加 deep=True:
-
df.memory_usage(deep=True).sum()才是真实内存用量(单位字节) - 对比时用同一份 CSV 数据,分别用 Pandas 1.5 和 2.2+ 读取,其他参数一致
- 重点比
string[pyarrow]vsobject:前者百万行英文城市名约 45 MB,后者常超 200 MB -
df['col'].astype('string')不等于string[pyarrow]——它转的是 Pandas 自研的StringDtype,内存几乎不降
为什么 .str 操作在 2.x 里更快?
不是因为算法变了,而是底层数据结构变了:string[pyarrow] 把所有字符串存进连续内存块 + 空值位图,.str.len()、.str.contains() 这类操作可以直接向量化执行,不用逐个构造 Python 字符串对象。
- 实测
.str.contains('abc')在百万行上,object耗时约 1.8s,string[pyarrow]仅 0.23s - 但注意:如果列里混了非字符串值(比如数字或 NaN),
string[pyarrow]会直接报错,而object会静默跳过或返回 False——这是严格性提升,不是 bug -
.str.split().str[0]这类链式操作在 2.x 中也受益于写入时复制(CoW),中间 Series 不立即拷贝内存
read_csv 时怎么避免 fallback 到 object?
很多人装了 PyArrow、升级了 Pandas 2.x,但读出来还是 object ——根本原因是没配对使用两个参数:
-
engine='pyarrow'只控制 CSV 解析器用 C++ 还是 Python,快但不改内存表示 -
dtype_backend='pyarrow'才决定解析完的数据存在哪儿:Arrow 内存块 or Python 对象堆 - 必须同时写:
pd.read_csv('data.csv', engine='pyarrow', dtype_backend='pyarrow') - 漏掉
dtype_backend,哪怕engine='pyarrow',字符串列大概率仍是object - 如果文件里某列有混合类型(如 "123", "N/A", 456),Arrow 推断会更激进,可能直接报错而非容忍——这是暴露脏数据,不是缺陷
merge 时字符串 key 性能翻倍的前提是什么?
不是升级就自动生效。Pandas 2.x 的 hash join 加速只在满足全部条件时触发:
立即学习“Python免费学习笔记(深入)”;
- 参与 merge 的所有 key 列 dtype 必须是
string[pyarrow](或int64[pyarrow]等 Arrow 类型),任一列是object就整条路径降级 - 推荐写法:
df1 = pd.read_csv(..., dtype_backend='pyarrow'),再df1['key'] = df1['key'].astype('string[pyarrow]') -
how='inner'或how='left'且 key 列无 null 时加速最明显;how='outer'或含大量 null 会 fallback - 检查是否生效:运行
merge前先import pyarrow.compute as pc; print(pc.__version__),再观察 CPU 是否多核并行、内存增长是否平缓
真正卡住多数人的不是“要不要升级”,而是“升了之后没配对参数,结果还在 object 上硬跑”。Arrow 后端不是开关,是需显式声明的内存契约。



















