我们的团队在使用Spark API时遇到很多问题,尤其是大型架构表。我们目前有一个用Scala编写的程序,它利用Apache spark API从原始文件创建两个Hive表。我们有一个特别大的原始数据文件,它给我们的问题包含大约4700列和~200,000行。
我们每周都会收到一个新文件,显示上周发生的更新,插入和删除。我们的程序将创建两个表 - 主表和历史表。主表将是此表的最新版本,而历史记录表显示发生在此表中的所有更改插入和更新,并显示更改的内容。例如,如果我们有以下架构,其中A和B是主键:
Week 1 Week 2
|-----|-----|-----| |-----|-----|-----|
| A | B | C | | A | B | C |
|-----|-----|-----| |-----|-----|-----|
| 1 | 2 | 3 | | 1 | 2 | 4 |
|-----|-----|-----| |-----|-----|-----|
然后主表将是
|-----|-----|-----|
| A | B | C |
|-----|-----|-----|
| 1 | 2 | 4 |
|-----|-----|-----|
历史表将是
|-----|-----|-------------------|----------------|-------------|-------------|
| A | B | changed_column | change_type | old_value | new_value |
|-----|-----|-------------------|----------------|-------------|-------------|
| 1 | 2 | C | Update | 3 | 4 |
|-----|-----|-------------------|----------------|-------------|-------------|
此过程可以完美地用于更短的模式表。我们有一个包含300列但超过100,000,000行的表,此代码仍按预期运行。上面针对较大模式表的过程运行大约15个小时,然后崩溃并出现以下错误:
Exception in thread "main" java.lang.StackOverflowError
at scala.collection.generic.Growable$class.loop$1(Growable.scala:52)
at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:57)
at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:183)
at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:45)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241)
at scala.collection.immutable.List.flatMap(List.scala:344)
这是一个代码示例,对于这个较大的表运行大约需要4个小时,但对于其他表运行大约需要20秒:
var dataframe_result = dataframe1.join(broadcast(dataframe2), Seq(listOfUniqueIds:_*)).repartition(100).cache()
我们尝试了以下所有方法但没有成功:
导致此错误的原因是什么?我们如何解决?这个问题表之间的唯一区别是它有很多列。 Spark可以处理的列数有上限吗?
注意:我们在一个非常大的MAPR集群上运行此代码,我们尝试提供500GB的RAM代码,但仍然失败。