You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Polars处理30GB大文件内存分配失败:脚本或版本问题?

问题分析与解决方案

你的问题大概率是脚本内存效率不足+旧版本Polars的内存管理缺陷共同导致的,同时VS Code与Jupyter的环境差异也可能是触发因素。以下是具体的排查和优化方向:

一、脚本层面的内存优化

你的agg操作中,list的concat、flatten、unique组合会生成大量中间数据,在处理全量2600万条记录时会快速耗尽内存。可以从以下几点优化:

1. 提前过滤无效数据,减少中间list的大小

原逻辑是先concat所有内容再过滤,改成先对每个字段过滤再concat,大幅减少后续list处理的数据量:

(
    df
    .group_by(person_id_key, person_source_id_key, "person_source_type")
    .agg(        
        # 优化后的Name字段处理
        pl.concat_list(
            # 先过滤full_name
            pl.col(full_name_key).fill_null("").filter(~pl.element().is_in(special_removal)),
            # 拆分nickname后直接过滤
            pl.col(nickname_key).fill_null("").str.split("|").list.eval(pl.element().filter(~pl.element().is_in(special_removal))),
            # 先过滤拼接后的全名
            (pl.col(first_name_key).fill_null("") + " " + pl.col(last_name_key).fill_null("")).filter(~pl.element().is_in(special_removal))
        )
        .flatten()
        .unique()
        .alias("name"),

        # 优化Company字段:提前去重再concat
        pl.concat_list(
            pl.col(org_name_key).unique(),
            pl.col(master_org_name_key).unique()
        )
        .flatten()
        .unique()
        .alias("company")
    )
    .with_columns(pl.col('name').list.len().alias("size_of_name"))
    .filter(pl.col("size_of_name") >= 1)
    .drop("size_of_name")
)

2. 切换到Polars Lazy API

Lazy模式会自动优化执行计划,减少不必要的内存开销(比如延迟计算、合并操作步骤),对于大文件处理效率提升明显:

(
    df.lazy()  # 启用lazy模式
    .group_by(person_id_key, person_source_id_key, "person_source_type")
    .agg(        
        pl.concat_list(
            pl.col(full_name_key).fill_null("").filter(~pl.element().is_in(special_removal)),
            pl.col(nickname_key).fill_null("").str.split("|").list.eval(pl.element().filter(~pl.element().is_in(special_removal))),
            (pl.col(first_name_key).fill_null("") + " " + pl.col(last_name_key).fill_null("")).filter(~pl.element().is_in(special_removal))
        ).flatten().unique().alias("name"),
        pl.concat_list(pl.col(org_name_key).unique(), pl.col(master_org_name_key).unique()).flatten().unique().alias("company")
    )
    .with_columns(pl.col('name').list.len().alias("size_of_name"))
    .filter(pl.col("size_of_name") >= 1)
    .drop("size_of_name")
    .collect()  # 最终触发计算
)

3. 排查分组基数

如果person_id_key等分组键的唯一值接近2600万(几乎每条记录一个分组),agg后的list数据会直接占用大量内存。可以先执行以下代码查看分组数量:

print(df.select(person_id_key, person_source_id_key, "person_source_type").n_unique())

如果分组基数过大,需要考虑调整分组策略,或者对分组结果做分批处理。

二、环境差异排查

Jupyter能运行但VS Code失败,可能是环境配置不同:

  • 确认两者使用的Python环境一致:分别在Jupyter和VS Code的终端执行import polars; print(polars.__version__)和import sys; print(sys.executable),检查版本和Python路径是否相同。
  • 关闭VS Code的调试模式:调试模式会额外占用内存,尝试直接在终端运行脚本而非通过调试按钮启动。
  • 检查Windows虚拟内存设置:打开「系统属性-高级-性能设置-高级-虚拟内存」,确保虚拟内存已开启且分配足够空间(建议设置为物理内存的1.5-2倍,或选择「系统管理的大小」)。

三、升级Polars版本

Polars 0.17.2是较旧的版本(发布于2023年初),后续版本(0.18+)对group_by、list操作的内存管理做了大量优化,修复了多个内存泄漏和低效问题。直接升级到最新稳定版本:

pip install --upgrade polars

补充建议

如果上述优化后仍有问题,可以:

  • 用Windows任务管理器监控Python进程的内存占用,定位到内存暴涨的具体操作步骤(比如concat_list还是unique)。
  • 生成与原数据结构一致的合成数据集,复现问题后进一步排查。

内容的提问来源于stack exchange,提问作者Jenobi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:24:55