在运行spark job时,我看到堆栈跟踪的OOM异常我发现physicalPlanDescription
太大了:
它在这里创建:(org.apache.spark.sql.execution.QueryExecution line:206)
private def completeString(appendStats: Boolean): String = {
...
...
s"""== Parsed Logical Plan ==
|${stringOrError(logical.treeString(verbose = true))}
|== Analyzed Logical Plan ==
|$analyzedPlan
|== Optimized Logical Plan ==
|${stringOrError(optimizedPlanString)}
|== Physical Plan ==
|${stringOrError(executedPlan.treeString(verbose = true))}
""".stripMargin.trim
}
根据代码中的注释为UI创建。
1)我该怎么办?已经使用了20G堆的驱动程序。
2)为什么这个字符串不是懒惰的?为什么要一直计算?
我也打开问题:Apache Spark
如下所示:link
使用-XX:+UseG1GC
为了清楚这个代码创建了一个非常大的计划,我的实际代码要复杂得多,许多表互相连接过滤和许多case when
语句。
所以请不要坚持这个示例代码实际上什么都不做的事实。
答案 0 :(得分:1)
我们面临同样的问题,解决方案是将参数“ spark.sql.ui.retainedExecutions”设置为较低的值,例如--conf "spark.sql.ui.retainedExecutions=10"
。
默认情况下为1000。
它将org.apache.spark.sql.execution.ui.SQLExecutionUIData的实例计数保持在足够低的水平。
SQLExecutionUIData具有对physicalPlanDescription的引用,该引用可能会很大。
在我们的案例中,我们不得不从卡夫卡那里读取大量的非凡消息,其中包含很多字段,而每个计划的描述都在8mg左右。
答案 1 :(得分:0)
如果您不需要UI,可以尝试将spark.ui.enabled设置为false。
答案 2 :(得分:0)
您可以使用 spark.sql.maxPlanStringLength=8000 <number of bytes>
配置截断物理计划并控制要在 UI 上显示的字符串的长度。
Spark 在 3.0.0 版本中引入了这个配置。
为计划字符串输出的最大字符数。如果计划更长,则进一步的输出将被截断。默认设置始终生成完整计划。如果计划字符串占用过多内存或导致驱动程序或 UI 进程中出现 OutOfMemory 错误,请将其设置为较低的值,例如 8k。