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

Polars读写Parquet时use_pyarrow参数配置性能差异问题咨询

问题概述

Polars 进行 Parquet 文件读写时,use_pyarrow 参数的不同配置组合会产生显著性能差异:

  • 性能最优组合:写入调用df.write_parquet时设置use_pyarrow=True,读取调用pl.read_parquet时设置use_pyarrow=False
  • 性能明显下降场景:读写两端均设置use_pyarrow=False时,Parquet 读取速度会大幅降低
  • 补充测试现象:当测试代码中np.random.randint(0, x, size=1000000)的x取值与size参数相等时,不同参数组合的性能差会出现边际递减。
复现代码
import time
import polars as pl
import numpy as np


df = pl.DataFrame(
    {
        f"{i}": np.random.randint(0, 120, size=3000000,)
        for i in ("A", "B", "C", "D", "E", "F", "G", "H", 'I', "J", 'K',)
    }
)


def repeat_read(arrow_read: bool, arrow_write: bool, n_times: int = 25) -> float:
    df.write_parquet('parquet', use_pyarrow=arrow_write)

    timings = []
    for i in range(n_times):
        time_start = time.time()
        some_var = pl.read_parquet('parquet', use_pyarrow=arrow_read)
        timings.append(time.time() - time_start)
    return sum(timings) / len(timings)

for i in range(3):
    print(f"Run {i}")
    read_write_false = repeat_read(arrow_read=False, arrow_write=False)
    print(f"Read-Write False: {read_write_false}")

    read_write_true = repeat_read(arrow_read=True, arrow_write=True)
    print(f"Read-Write Truee: {read_write_true}")

    read_false_write_true = repeat_read(arrow_read=False, arrow_write=True)
    print(f"Read False, Write True: {read_false_write_true}")

    read_true_write_false = repeat_read(arrow_read=True, arrow_write=False)
    print(f"Read True, Write False: {read_true_write_false}")
    print('---------------------------------------------------------\n')
基准测试结果
Read-Write False: 0.11888686180114746
Read-Write Truee: 0.14296542167663573
Read False, Write True: 0.07793953895568848
Read True, Write False: 0.16698485374450683
结论说明

该现象不属于Bug,是Polars原生Parquet实现、PyArrow Parquet实现的默认编码策略和数据转换开销共同导致的:

  • 读取端开启use_pyarrow=True时,无论文件由哪种方式写入,读取流程都会多一步「PyArrow Table 转 Polars 内存格式」的跨库拷贝转换,这部分固定开销会直接拉低读取速度,这也是read=True, write=False组合速度最慢的核心原因。
  • PyArrow的Parquet写入器默认对低基数列的字典编码触发阈值更低,测试用数据集所有列取值范围都是0-119,属于极低基数整数列,PyArrow写入时会自动开启字典编码,生成的Parquet文件数据页布局更紧凑、元数据结构更适配Polars原生读取器的批量解析逻辑,因此原生读取PyArrow生成的文件时速度最快。
  • 旧版本Polars原生Parquet写入器的字典编码触发策略更保守,对这类低基数整数列不会自动启用字典编码,生成的文件数据块更大、解码计算量更高,因此原生读取原生写入的文件时速度更慢。
  • 观察到的「x与size相等时性能差边际递减」现象也和编码逻辑完全匹配:当x和数据量size相等时,列的基数接近100%,字典编码不会带来任何存储和解析优势,两种写入器都会退回普通整数直写编码,生成的文件结构趋同,性能差自然会收窄。
实践建议
  • 若追求稳定极致性能,可直接采用use_pyarrow=True写入、use_pyarrow=False读取的组合,无需额外调整编码参数。
  • 若不想引入PyArrow依赖,可升级到最新稳定版Polars,新版本已经调整了原生Parquet写入的字典编码触发规则,低基数列的编码策略已经和PyArrow对齐,两端均使用原生实现的性能差已经基本消除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:54:29