2016-02-24 56 views
1

我想通過在列數爲200+的Scala程序中創建RDD來創建Spark SQL表。編譯(SBT編譯)失敗,java.lang.StackOverflowError的例外,當我創建我的架構爲:Spark SQL表最大列數

StructField("RT", StringType,nullable = true) :: 
StructField("SERIALNO", StringType,nullable = true) :: 
StructField("SPORDER", StringType,nullable = true) :: 
// ... remaining 200+ columns 

無法粘貼堆棧跟蹤,因爲它是超過1.5K線

在減少列數大約100-120編譯成功。另外,當我使用模式字符串創建模式(拆分模式字符串,然後創建它的映射)時,編譯成功(在標題爲「以編程方式指定模式https://spark.apache.org/docs/1.3.0/sql-programming-guide.html中的第一個示例)。

什麼似乎是手動指定架構導致異常的問題?

+1

在你的錯誤堆棧創建一個要點,並把它添加到問題,請!你的問題是不可挽救的,因爲它是現在和相當廣泛,很明顯,它會被投票關閉 – eliasah

+0

我猜自動模式檢測使用遞歸,它是'tailrec'。我會在Spark JIRA上發佈一個問題。 – Reactormonk

+0

@Reactormonk無需報告。這是一個斯卡拉「問題」,而不是Spark問題。見下文。 – DemetriKots

回答

2

這裏的基本問題是,您在每個StructField的每個步驟都要進行列表級聯。 operator ::實際上是List而不是StructField的成員。雖然代碼讀取:

val fields = field1 :: field2 :: field3 :: Nil 

這相當於:

val fields = field1 :: (field2 :: (field3 :: Nil)) 

甚至

val fields = Nil.::(field1).::(field2).::(field3) 

因此,在執行過程中,JVM需要遞歸地評估該::方法調用。 JVM按照列表中項目的數量增加堆棧的深度。拆分字段名稱和映射工作字符串的原因是因爲它遍歷字段名稱的拆分字符串而不是使用遞歸。

這不是一個Spark問題。一旦進入數百個項目,您可以在Scala repl中的任何類型的一系列List串聯中重現此相同的堆棧溢出錯誤。只需使用其他方法之一來創建不會導致堆棧溢出的StructField列表。

例如,這樣的事情會工作得很好:

val structure = StructType(
    List(
    StructField("RT", StringType,nullable = true), 
    StructField("SERIALNO", StringType,nullable = true), 
    StructField("SPORDER", StringType,nullable = true), 
    // Other Fields 
    StructField("LASTFIELD", StringType,nullable = true) 
) 
)