Azure DataBricks内存未释放问题:根源排查与解决方法咨询
Azure Databricks读取海量嵌套JSON数据后内存无法释放的问题
环境与场景
- 平台:Azure DataBricks 12.2 LTS(内置Apache Spark 3.3.2、Scala 2.12)
- 计算节点:Standard_DS5_v2
- 问题:从Delta表读取含大量嵌套JSON的海量数据,执行代码后Ganglia集群面板显示内存未释放,已尝试
df.unpersist()、del df、df=None配合gc.collect()均无效。
执行代码
df_spark = spark.sql(my_qyery_to_delta_table) df_pandas = df_spark.toPandas() df_spark.unpersist() import gc del df_pandas del df_spark gc.collect()
问题根源
- Spark自动缓存残留:Spark SQL执行时会自动缓存查询结果(尤其是涉及Shuffle或重复执行的场景),单个DataFrame的
unpersist()无法清理所有Spark层面的缓存数据,导致JVM内存占用未释放。 - Python与JVM内存隔离:
toPandas()将Executor端数据全量拉取到Driver节点的Python进程中,嵌套JSON结构生成的复杂Python对象可能存在隐式引用(如Spark内部元数据关联),Python GC无法彻底回收;同时Spark的JVM层面内存需要JVM自身GC回收,Python的gc.collect()无法触发JVM GC。 - Driver节点内存泄漏:Notebook环境中,之前单元格的变量引用、Spark会话残留资源可能导致内存无法回收,嵌套JSON的复杂结构会加剧此类问题。
- Ganglia统计延迟:Ganglia内存指标存在一定统计延迟,若长时间未下降则属于内存未实际释放。
解决方法
- 清理全量Spark缓存:执行
spark.catalog.clearCache()替代单个DataFrame的unpersist(),彻底清除Spark层面所有缓存的表和DataFrame数据。 - 触发JVM层面GC:通过Python调用JVM的GC机制,执行
spark.sparkContext._jvm.System.gc(),强制回收JVM占用的内存。 - 优化数据拉取逻辑:在Spark层面先做过滤、聚合或字段裁剪,减少
toPandas()拉取到Driver的数据量;若不需要全量数据,优先使用limit()或采样操作缩小数据规模。 - 关闭Spark自动缓存:在Notebook开头添加配置
spark.conf.set("spark.sql.cache.enabled", "false"),禁止Spark自动缓存查询结果,避免不必要的内存占用。 - 隔离测试环境:在全新的Notebook中单独执行代码,避免之前单元格的变量引用干扰内存回收。
- 调整Driver内存配置:若Driver节点内存长期不足,可在集群配置中增大
spark.driver.memory值,或配合升级节点规格(如使用更大的DS系列节点)。
内容的提问来源于stack exchange,提问作者RunTheGauntlet
相关产品推荐
相关产品推荐

