如何在Python中释放DuckDB占用的内存?
如何释放DuckDB占用的内存?
你的代码存在几个导致内存无法释放的问题,以下是针对性的解决方案和优化后的代码:
核心问题分析
- 循环内定义函数会延长变量生命周期,Python垃圾回收无法及时清理大对象
- 使用全局的
duckdb.sql()会依赖隐含的全局连接,该连接的资源不会自动释放 - 未显式释放PyArrow表、DeltaTable等大对象,也未强制触发垃圾回收
优化步骤与代码
import duckdb import deltalake import gc def process(src): con = duckdb.connect(":memory:") try: # 可选:设置DuckDB内存限制,防止内存溢出 con.sql("PRAGMA memory_limit='16GB'") # 直接用DuckDB读取Delta Lake,避免全量加载到PyArrow表(更省内存) con.sql(f""" SELECT * FROM delta_scan('s3a://{src}', storage_options={deltalake_storage_options}) """).write_parquet("/tmp/test.parquet") # 若需保留原逻辑,需显式释放资源 # dt = deltalake.DeltaTable(f"s3a://{src}", storage_options=deltalake_storage_options) # pa = dt.to_pyarrow_table() # con.from_arrow(pa).write_parquet("/tmp/test.parquet") # del pa, dt finally: # 强制DuckDB释放内存 con.sql("PRAGMA release_memory") # 关闭连接 con.close() # 触发Python垃圾回收,清理残留对象 gc.collect() for src in ["a","b", "c"]: process(src)
关键优化点说明
- 避免全局DuckDB调用:改用连接对象的
con.sql(),资源绑定到当前连接,关闭时能彻底释放 - 显式资源清理:用
del删除大对象,再调用gc.collect()强制回收内存 - DuckDB内存指令:
PRAGMA release_memory会强制DuckDB释放未使用的内存;memory_limit可以限制单连接的内存使用上限 - 直接读取Delta Lake:通过
delta_scan让DuckDB按需加载数据,无需把全表读到PyArrow,大幅降低内存占用
内容的提问来源于stack exchange,提问作者Syrius
相关产品推荐
相关产品推荐

