Apache spark 如何在Spark中读取嵌套集合

Apache spark 如何在Spark中读取嵌套集合,apache-spark,apache-spark-sql,nested,parquet,lateral-join,Apache Spark,Apache Spark Sql,Nested,Parquet,Lateral Join,我有一张镶木地板的桌子,桌子上有一根柱子 ,数组 可以在配置单元中使用横向视图语法对此表运行查询 如何将此表读入RDD,更重要的是如何过滤、映射Spark中的嵌套集合 在Spark文档中找不到对此的任何引用。提前感谢您提供的任何信息 另外,我觉得在桌面上提供一些数据可能会有帮助。 主表中的列数~600。行数~200m。 嵌套集合中的“列”数~10。嵌套集合中的平均记录数~35 在嵌套集合的情况下没有魔力。Spark将以相同的方式处理RDD[(字符串,字符串)]和RDD[(字符串,序列[Strin

我有一张镶木地板的桌子,桌子上有一根柱子

,数组

可以在配置单元中使用横向视图语法对此表运行查询

如何将此表读入RDD,更重要的是如何过滤、映射Spark中的嵌套集合

在Spark文档中找不到对此的任何引用。提前感谢您提供的任何信息

另外,我觉得在桌面上提供一些数据可能会有帮助。 主表中的列数~600。行数~200m。
嵌套集合中的“列”数~10。嵌套集合中的平均记录数~35

在嵌套集合的情况下没有魔力。Spark将以相同的方式处理
RDD[(字符串,字符串)]
RDD[(字符串,序列[String])]

不过,从拼花文件中读取这样的嵌套集合可能很棘手

让我们以火花壳(1.3.1)为例:

编写拼花地板文件:

scala> val outers = sc.parallelize(List(Outer("k1", List(Inner("a", "b")))))
outers: org.apache.spark.rdd.RDD[Outer] = ParallelCollectionRDD[0] at parallelize at <console>:25

scala> outers.toDF.saveAsParquetFile("outers.parquet")
请注意,我们仅使用spark SQL库读取拼花地板文件。例如,在将数据帧映射到RDD之前,您可以直接在数据帧上选择所需的列

dataFrame.select('col1, 'col2).map { row => ... }

我将给出一个基于Python的答案,因为这就是我正在使用的。我认为Scala也有相似之处

Spark 1.4.0中添加了
explode
函数,用于处理数据帧中的嵌套数组

创建测试数据帧:

from pyspark.sql import Row

df = sqlContext.createDataFrame([Row(a=1, intlist=[1,2,3]), Row(a=2, intlist=[4,5,6])])
df.show()

## +-+--------------------+
## |a|             intlist|
## +-+--------------------+
## |1|ArrayBuffer(1, 2, 3)|
## |2|ArrayBuffer(4, 5, 6)|
## +-+--------------------+
使用
explode
展平列表列:

from pyspark.sql.functions import explode

df.select(df.a, explode(df.intlist)).show()

## +-+---+
## |a|_c0|
## +-+---+
## |1|  1|
## |1|  2|
## |1|  3|
## |2|  4|
## |2|  5|
## |2|  6|
## +-+---+

另一种方法是使用如下模式匹配:

val rdd: RDD[(String, List[(String, String)]] = dataFrame.map(_.toSeq.toList match { 
  case List(key: String, inners: Seq[Row]) => key -> inners.map(_.toSeq.toList match {
    case List(a:String, b: String) => (a, b)
  }).toList
})

您可以直接在行上进行模式匹配,但由于一些原因可能会失败。

以上答案都是很好的答案,可以从不同的角度解决这个问题;Spark SQL也是访问嵌套数据的非常有用的方法

下面是如何在SQL中直接使用explode()查询嵌套集合的示例

SELECT hholdid, tsp.person_seq_no 
FROM (  SELECT hholdid, explode(tsp_ids) as tsp 
        FROM disc_mrt.unified_fact uf
     )
tsp_id是一个嵌套的结构,它有许多属性,包括我在上面的外部查询中选择的person_seq_no

以上内容在Spark 2.0中进行了测试。我做了一个小测试,但它在Spark 1.6中不起作用。这个问题是在Spark 2不存在时提出的,所以这个答案很好地添加到了处理嵌套结构的可用选项列表中

还可以查看以下JIRAs for Hive兼容方式,使用
横向视图外部
语法查询嵌套数据,因为Spark 2.2还支持
外部
分解(例如,当嵌套集合为空时,但您仍然希望具有父记录的属性):

对于SQL访问,在explode()上注意到未解析JIRA:


感谢您的详细回复。我已将其标记为正确响应。虽然我们还没有达到Spark 1.3,但计划在本月升级。Spark 1.2中是否可以不使用数据帧API?您能告诉我getAs[Seq[Row]](1)是如何工作的吗?索引[1]是包含嵌套数组的列的位置,对吗?请参阅我的编辑。对于Spark 1.2,您可以使用完全相同的代码将
转换为案例类。请参考官方文档,了解在旧版本中读取拼花地板文件的语法,非常接近。明白了。谢谢。GetSeq[Row](1)也可以吗?不客气。是的,
getSeq[Row]
将是另一种选择。不过,我不确定Spark 1.2中是否提供了这种方法。我让你查一下。我今天在user@spark.apache.orgSpark SQL直接支持横向视图语法的列表。一旦进入Spark 1.3,我们将尝试两种方法;(等待CDH 5.4.1发布,然后才能升级)谢谢dnlbrky。它看起来比Scala更容易阅读。我一定会试试你的python示例。。我们可能不会有Spark 1.4,但直到今年年底Cloudera发布CDH 5.5:-)希望到那时有Spark 1.5。explode是一项昂贵的操作,你能想出其他方法吗?
from pyspark.sql.functions import explode

df.select(df.a, explode(df.intlist)).show()

## +-+---+
## |a|_c0|
## +-+---+
## |1|  1|
## |1|  2|
## |1|  3|
## |2|  4|
## |2|  5|
## |2|  6|
## +-+---+
val rdd: RDD[(String, List[(String, String)]] = dataFrame.map(_.toSeq.toList match { 
  case List(key: String, inners: Seq[Row]) => key -> inners.map(_.toSeq.toList match {
    case List(a:String, b: String) => (a, b)
  }).toList
})
SELECT hholdid, tsp.person_seq_no 
FROM (  SELECT hholdid, explode(tsp_ids) as tsp 
        FROM disc_mrt.unified_fact uf
     )