使用Apache Spark在AWS Glue读取JSON文件时遭遇Driver内存溢出问题
解决Spark读取嵌套JSON时Driver内存溢出(OOM)问题
问题背景
我们用AWS Glue(仅使用Spark原生功能,为后续迁移Amazon EMR做准备)读取S3存储桶中的JSON文件:
- 输入数据:21个100MB的JSON文件,每个文件包含多个独立JSON对象(尝试转为合法JSON数组并启用
multiline=true后问题依旧) - 真实数据结构:25个顶层字段,其中7个为嵌套字段,展开后共约200个字段
- 任务配置:G.2X Worker(20个),额外Spark参数
--conf spark.driver.maxResultSize=2g --conf spark.yarn.executor.memory=7g --conf spark.driver.memory=20g - 核心问题:执行
spark.read.option("inferSchema", true).json(...)时,Driver内存占满触发OOM,Executor内存正常,小数据集可正常处理
原因分析
你遇到的Driver OOM核心原因是**inferSchema的工作机制**:
- Spark默认会采样输入文件(默认采样比例100%)来推断JSON的Schema,采样过程中,Executor会将采样的JSON数据传输到Driver端
- 对于高度嵌套、字段极多的JSON结构,Driver需要解析这些采样数据并构建复杂的
StructTypeSchema对象,这个过程会占用大量堆内存——尤其是当采样数据量较大(比如21个100MB文件的全量采样)时,Driver的内存会被快速耗尽 - 即使没有主动调用
collect()等将数据拉到Driver的操作,Schema推断的采样数据已经被传输到Driver处理,这就是Driver内存溢出的根本原因
解决方案
1. 手动定义Schema,彻底禁用inferSchema
这是最可靠的解决方案,完全避免Schema推断带来的Driver内存开销:
- 先通过小数据集生成并导出Schema(比如用
df.printSchema()输出结构),再手动编写对应的StructType - Scala示例代码:
import org.apache.spark.sql.types._ // 替换为你真实数据的完整Schema结构 val customSchema = StructType(Seq( StructField("RecordNumber", IntegerType, nullable = true), StructField("Zipcode", IntegerType, nullable = true), // 嵌套字段示例 StructField("UserInfo", StructType(Seq( StructField("UserName", StringType, nullable = true), StructField("Contact", StructType(Seq( StructField("Phone", StringType, nullable = true), StructField("Email", StringType, nullable = true) )), nullable = true) )), nullable = true), // 剩余22个顶层字段依次补充... )) // 使用自定义Schema读取JSON val df = spark.read.schema(customSchema).json("s3://bucket_with_json/sub_folder")
- 技巧:可以先用小数据集运行
inferSchema,然后将df.schema的输出复制出来作为自定义Schema的模板,避免手动编写出错
2. 调整Schema推断的采样参数(应急方案)
如果暂时无法手动定义Schema,可通过减少采样比例降低Driver的内存压力:
- 添加Spark配置参数:
--conf spark.sql.jsonSchema.inferSampleRatio=0.1(表示仅采样10%的数据) - 注意:采样比例过低可能导致Schema推断不准确(比如某些低频字段的类型被误判),需要验证最终DataFrame的Schema是否符合预期
3. 优化Driver内存相关配置
- 调大
spark.driver.maxResultSize:默认2G可能不足以容纳复杂Schema推断的中间结果,建议改为4g或unlimited(使用unlimited需谨慎,避免Driver内存失控),配置示例:--conf spark.driver.maxResultSize=4g - 确认Glue实例的Driver内存上限:G.2X实例的Driver内存是否支持20G,若实例本身内存不足,调大参数也无法生效,可考虑升级Worker实例类型
4. 预处理数据(备选方案)
- 将大文件拆分为更小的文件,减少单次采样的数据量
- 预处理JSON文件,扁平化嵌套结构,降低Schema的复杂度,减少Driver解析Schema的内存开销
内容的提问来源于stack exchange,提问作者RudyVerboven
相关产品推荐
相关产品推荐

