Polars与Pandas内存消耗相近,其优势何在?求内存优化建议
问题:Polars与Pandas从Oracle读取SQL的内存占用及速度差异疑惑
我对比了Polars和Pandas从Oracle数据库读取同一条SQL查询结果的内存消耗,结果显示二者内存占用几乎相同,且Pandas的执行速度比Polars快一倍。我原本预期Polars的内存效率更高,希望有人解释这一现象,并给出缩减该数据集内存占用的建议。
Polars读取SQL的执行情况

Pandas读取SQL的执行情况

数据集形状(Polars的result与Pandas的data)

内存占用对比

现象解释
- 驱动层数据传输的一致性:从Oracle读取数据时,两者都依赖数据库驱动(如cx_Oracle)获取原始数据,再转换为各自的数据结构。如果驱动返回的是Python对象而非原生紧凑类型,Polars的内存优化优势就难以体现——此时转换前的内存占用已经占了大头,Polars的内部存储优化无法覆盖驱动层面的开销。
- 数据类型推断无差异:如果Polars和Pandas对查询结果的列类型推断完全一致(比如都用
int64、object类型存储相同列),内存占用自然接近。Polars的内存优势通常体现在自动压缩可优化类型(如字符串用Utf8而非Python对象、整数用更小位宽),但如果Oracle返回的数据类型限制了推断空间,这种优势会消失。 - 读取策略的兼容性差异:Pandas的
read_sql可能在特定场景下与Oracle驱动的兼容性更好,采用了更高效的批量读取策略;而Polars的read_sql可能在数据转换环节存在额外的类型校验、中间结构转换开销,导致速度变慢。
内存缩减建议
- 显式指定列类型:避免自动推断带来的冗余类型,根据数据范围手动指定紧凑类型:
# Polars指定类型 schema = {"id": pl.Int32, "name": pl.Utf8, "value": pl.Float32} result = pl.read_sql(query, connection, schema=schema) # Pandas指定类型 dtype = {"id": "int32", "name": "string", "value": "float32"} data = pd.read_sql(query, connection, dtype=dtype) - 分块读取数据:针对大数据集,采用分块读取减少一次性内存占用:
# Polars分块读取 for chunk in pl.read_sql(query, connection, batch_size=10000): process(chunk) # Pandas分块读取 chunk_iter = pd.read_sql(query, connection, chunksize=10000) for chunk in chunk_iter: process(chunk) - 数据库层面优化:在SQL查询中提前过滤不必要的行/列,将字符串类型转换为Oracle的
VARCHAR2而非CLOB,减少传输的数据量。 - Polars专属优化:使用
optimize()自动优化列类型,或手动将列转换为Categorical等紧凑类型:result = result.optimize() result = result.with_columns(pl.col("category").cast(pl.Categorical)) - Pandas专属优化:用
pd.to_numeric()压缩数值列,或转换字符串列为Categorical类型:data["id"] = pd.to_numeric(data["id"], downcast="integer") data["category"] = data["category"].astype("category")
内容的提问来源于stack exchange,提问作者Atacan
相关产品推荐
相关产品推荐

