Spark RDD元组数量限制引发ArrayIndexOutOfBoundsException问题咨询
解决Scala 2.11及之前元组限制与RDD读取数组越界问题
嘿,我来帮你搞定这两个头疼的问题——Scala老版本的元组元素数量限制,还有读取Hive表RDD时的数组越界异常!
先搞定元组22列的限制
Scala 2.11.8及更早版本确实有个硬限制:元组最多只能装22个元素,这就是你从25列DataFrame转RDD时卡壳的原因。不过有两种好用的办法绕开这个限制:
方案1:用Case Class替代元组(推荐!)
自定义一个和你表结构完全匹配的Case Class,把DataFrame的每一行映射成这个类的实例,这样转成RDD就完全不受元组限制了,而且类型安全,后续处理数据也更清晰。举个例子:
// 按你的表结构定义Case Class,字段名和类型对应上就行 case class MyRecord( date: String, accId: String, userId: Int, col4: Int, col5: Int, col6: Double, col7: Double, col8: Double, col9: Double, col10: Double, col11: Double, col12: Double, col13: Double, col14: Double, col15: Double, col16: Double, col17: Double, col18: Double, col19: Double, col20: Double, col21: Double, col22: Double, col23: Double, col24: Double, col25: Double ) // 从Hive表读DataFrame,再转成RDD[MyRecord] val df = spark.table("myDB.myTable") val rdd = df.as[MyRecord].rdd
方案2:用Array/List打包字段(临时救急)
如果不想写Case Class,也可以把DataFrame的行转成Array或者List,不管多少列都能装下,缺点是会丢失类型信息,后续处理需要手动转类型:
val df = spark.table("myDB.myTable") val rdd = df.rdd.map(row => row.toSeq.toArray)
再解决ArrayIndexOutOfBoundsException异常
你直接用sc.textFile读Hive仓库的底层文件,抛出数组越界,核心原因是Hive表的存储格式不是纯文本(比如ORC、Parquet),你用textFile读取会把二进制/结构化文件当成纯文本行解析,拆分字段时自然会出现下标越界的情况。
正确的打开方式:通过Spark SQL读表
别直接碰Hive仓库的底层文件,用Spark SQL读取表数据再转RDD,Spark会自动识别存储格式,正确解析每一行:
// 方式1:用SparkSession读表转RDD(推荐) val df = spark.sql("SELECT * FROM myDB.myTable") val rdd = df.as[MyRecord].rdd // 搭配前面的Case Class使用 // 方式2:用HiveContext读取(老版本Spark可用) import org.apache.spark.sql.hive.HiveContext val hiveContext = new HiveContext(sc) val rdd = hiveContext.table("myDB.myTable").rdd
如果你的表确实是文本格式(比如CSV)
如果你的Hive表是用纯文本存储的(比如CSV、TSV),那可以用textFile读取,但要注意两个关键点:
- 拆分符要和Hive表的字段分隔符一致(Hive默认是ASCII的001,也就是
\u0001) - 过滤掉字段数量不对的行,避免越界
示例代码:
val rdd = sc.textFile("/user/hive/warehouse/myDB.db/myTable/") // 用Hive默认分隔符拆分每行 val parsedRdd = rdd.map(line => line.split("\u0001")) // 过滤掉字段数不等于25的行,防止越界 val validRdd = parsedRdd.filter(arr => arr.length == 25)
内容的提问来源于stack exchange,提问作者knowone
相关产品推荐
相关产品推荐

