当我想在apache-spark中获取超过1,000,000行时遇到OOM

时间:2015-06-10 07:33:25

标签: apache-spark

问题: 我想通过SparkSQL JDBC接口查询存储在Hive中的表。 并希望获取超过1,000,000行。但遇到了OOM。 sql = "select * from TEMP_ADMIN_150601_000001 limit XXX ";

我的环境: 5个节点=一个主人+4个工作人员,1000M网络交换机,Redhat 6.5 每个节点:8G RAM,500G硬盘 Java 1.6,Scala 2.10.4,Hadoop 2.6,Spark 1.3.0,Hive 0.13

数据: 有用户的桌子,有电费数据。 大约1,600,000行。大约28MB。 每行占用大约18个字节。 2列:user_id String, total_num Double

Repro步骤:  1.启动Spark  2.启动SparkSQL thriftserver,命令:

/usr/local/spark/spark-1.3.0/sbin/start-thriftserver.sh \
--master spark://cx-spark-001:7077 \
--conf spark.executor.memory=4g \
--conf spark.driver.memory=2g \
--conf spark.shuffle.consolidateFiles=true \
--conf spark.shuffle.manager=sort \
--conf "spark.executor.extraJavaOptions=-XX:-UseGCOverheadLimit" \
--conf spark.file.transferTo=false \
--conf spark.akka.timeout=2000 \
--conf spark.storage.memoryFraction=0.4 \
--conf spark.cores.max=8 \
--conf spark.kryoserializer.buffer.mb=256 \
--conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
--conf spark.akka.frameSize=512 \
--driver-class-path /usr/local/hive/lib/classes12.jar
  1. 运行测试代码,在附件中查看:testHiveJDBC.java
  2. 在120秒后获取OOM:GC开销限制或OOM:Java堆空间或丢失的工作者心跳。请参阅随附的日志。
  3. 初步诊断:  6.当获取少于1,000,000行时,它总是成功的。  7.当获取超过1,300,000行时,它总是因OOM而失败:超出GC开销限制。  8.当获取大约1,040,000-1,200,000行时,如果在thrift服务器启动后立即查询,则大多数时间成功。如果我成功查询一次然后重试相同的查询,它将失败。  9.有3种死模式:OOM:超出GC开销限制或OOM:java堆空间或120s后丢失的工作者心跳。  10.我尝试用不同的配置启动节俭,给工人4G MEM或2G MEM,得到相同的行为。这意味着,无论工人的总MEM,我都可以获得少于1,000,000行,并且不能超过1,300,000行。

    初步结论:  11.总数据小于30MB,非常小,并且没有复杂的计算操作。 因此,失败不是由过多的内存需求引起的。 所以我猜火花sql代码有一些缺陷。  12.为每个工作人员分配2G或4G MEM,行为相同。 这一点加强了我的疑虑:代码中存在一些缺陷。但我找不到具体的位置。

2 个答案:

答案 0 :(得分:1)

因为spark worker将所有任务结果发送到驱动程序(ThriftServer),驱动程序将collect all task results发送到org.apache.spark.sql.Row[TASK_COUNT][ROW_COUNT]数组。

这是制作ThriftServer OOM的根本原因。

答案 1 :(得分:0)

您还可以尝试将 <table class="table table-bordered"> <thead> <tr> <th></th> <th scope="col" class="col-md-5">Device Name</th> <th scope="col" class="col-md-7">Device MAC</th> </tr> {% for row in data %} <tr> <td> <input type="checkbox" name="selected_ids[]" value="{{row[ur_id_pos]}}"> </td> <td> {{row[0]}} </td> <td> {{row[1]}} </td> </tr> {% endfor %} </thead> </table> 设置为spark.sql.thriftServer.incrementalCollects。在https://issues.apache.org/jira/browse/SPARK-25224中很好地描述了这些效果!