【问题标题】:Spark OOM issue when writing dataframe to HDFS将数据帧写入 HDFS 时出现 Spark OOM 问题
【发布时间】:2018-12-25 20:36:32
【问题描述】:

在 Spark 2.3 中遇到此问题。

我在具有 7 个节点的 Cloudera 集群上运行任务:64 GB 内存,每个 16 个核心

相关配置:--conf spark.executor.memoryOverhead=5G --executor-memory 30G --num-executors 15 --executor-cores 5

错误是由 spark executors 引发的:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at java.lang.StringCoding.encode(StringCoding.java:350)
at java.lang.String.getBytes(String.java:941)
at org.apache.spark.unsafe.types.UTF8String.fromString(UTF8String.java:110)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificUnsafeProjection.StaticInvoke7$(Unknown Source)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificUnsafeProjection.apply(Unknown Source)
at org.apache.spark.sql.catalyst.encoders.ExpressionEncoder.toRow(ExpressionEncoder.scala:288)
at org.apache.spark.sql.SparkSession$$anonfun$4.apply(SparkSession.scala:589)
at org.apache.spark.sql.SparkSession$$anonfun$4.apply(SparkSession.scala:589)
at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)
at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$SingleDirectoryWriteTask.execute(FileFormatWriter.scala:380)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask$3.apply(FileFormatWriter.scala:269)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask$3.apply(FileFormatWriter.scala:267)
at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1411)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$.org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask(FileFormatWriter.scala:272)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$write$1.apply(FileFormatWriter.scala:197)
at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$write$1.apply(FileFormatWriter.scala:196)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
at org.apache.spark.scheduler.Task.run(Task.scala:109)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

这是我正在运行的代码:

val table_df = spark.createDataFrame(table,schema)
val table_df_filled = table_df.na.fill("null")
table_df_filled.write.mode("overwrite").csv("path")

我已尝试增加执行程序/驱动程序/开销内存;

我尝试通过spark.default.parallelismconf 将分区增加几倍(4000,8000);

关于数据大小,对于每一行(记录),有几个元数据列和一个大字符串列。我确信问题出在大字符串列上,我在该字段中保存了单个网页的完整 HTML 代码(我认为每个网页不超过 1 GB?)。总数据大小约为 100GB。

有没有人遇到过类似的问题?

一些跟进:

  • 我试图打印整个 RDD,它运行通过。
  • 通过依赖 Dataframe,任务因同样的问题而失败。 所以我猜这个问题与 Dataframe 列大小限制有关?
  • 我设法使用saveAsTextFile 直接从RDD 输出内容,没有任何问题。

【问题讨论】:

  • 您能否提供更多有关您尝试加载的数据大小以及数据来源和内存配置的详细信息
  • 写入前尝试通过调用table_df_filled.repartition(num_partitions)增加分区数。
  • 您好,信息如前所述。

标签: scala apache-spark dataframe hdfs cloudera


【解决方案1】:

事实证明,问题的原因是在从 RDD 转换 DataFrame 期间,某些记录达到了 Array 大小限制。在这种情况下,我有以下两种选择:

  • 将问题字符串列拆分为多个列(减小大小)。
  • 自己编写输出格式,直接从RDD通过saveAsTextFile函数将数据写入HDFS。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 2019-12-16
    • 1970-01-01
    • 2018-11-21
    相关资源
    最近更新 更多