pl.scan_csv()是百亿级数据唯一可行入口,因其惰性执行、列式加载和下推优化避免OOM,而pl.read_csv()会全量加载导致内存溢出。

pl.scan_csv() 是百亿级数据的唯一可行入口,pl.read_csv() 在这种规模下直接 OOM。
为什么必须用 scan_csv 而不是 read_csv
百亿行 CSV 文件解压后往往超 100GB,pl.read_csv() 会一次性全量加载进内存,哪怕你只想要其中一列或几行;而 pl.scan_csv() 不读数据,只建执行计划,后续 filter、select、group_by 都被下推到读取阶段——真正只加载需要的块和列。
- 不指定
dtypes会导致 Polars 扫描全量样本推断类型,启动慢且不准;务必显式传入{"id": pl.UInt64, "ts": pl.Datetime} - 有 header 但列名含空格或特殊字符时,别依赖
infer_schema_length,用new_columns重命名:pl.scan_csv("x.csv", new_columns=["col_a", "col_b"]) - 加
low_memory=True启用流式解析,避免临时缓冲区膨胀;配合row_count_name="idx"可省掉后续with_row_count()的额外遍历
filter 和 group_by 的写法差异直接影响性能
Pandas 的 .query("x > 100") 或布尔索引是 Python 层逐行判断,Polars 的 filter(pl.col("x") > 100) 是编译成 Rust 指令的向量化操作,无解释器开销。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 字符串过滤别用
str.contains("abc")做模糊匹配,优先用str.starts_with()或str.ends_with(),它们能触发 SIMD 加速 -
group_by("key").agg(...)默认走哈希分组;若 key 已排序且想保持顺序,加maintain_order=True可跳过重排 - 聚合时避免
agg(pl.col("x").apply(...))—— 这会退化为 Python 循环;所有计算必须用内置表达式,如pl.mean("x")、pl.max("y")
LazyFrame 的 collect() 时机决定内存峰值
惰性模式下,.filter().select().group_by().agg() 都不触发计算,直到调用 .collect() 才真正执行并返回 DataFrame。这个“收口”点必须手动控制。
- 中间结果不要反复
.collect(),比如先df1 = q.collect()再df2 = df1.filter(...).collect()—— 这会让两份数据同时驻留内存 - 调试时可用
.explain()看物理执行计划,确认 filter 是否被下推、是否用了并行扫描 - 如果最终要写 Parquet,直接链式调用
.collect().write_parquet("out.parq"),别拆成两步
scan_csv 时就想清楚:哪几列真需要?哪些条件能下推?聚合是否可合并?漏掉任何一个,都可能让内存从 2GB 暴涨到 40GB。

















