繁体   English   中英

将大量JSON文件读入Spark Dataframe

[英]Reading massive JSON files into Spark Dataframe

我有一个大的嵌套NDJ(新行分隔的JSON)文件,我需要读入一个火花数据帧并保存到镶木地板。 在尝试呈现模式时,我使用此函数:

def flattenSchema(schema: StructType, prefix: String = null) : Array[Column] = {
        schema.fields.flatMap(f => {
          val colName = if (prefix == null) f.name else (prefix + "." + f.name)
          f.dataType match {
            case st: StructType => flattenSchema(st, colName)
            case _ => Array(col(colName))
          }
        })
  }

在通过读取返回的数据帧上

val df = sqlCtx.read.json(sparkContext.wholeTextFiles(path).values)

我也把它切换到val df = spark.read.json(path) ,这样只适用于NDJ而不是多行JSON - 同样的错误。

这导致worker java.lang.OutOfMemoryError: Java heap space出现内存不足错误。

我已经改变了jvm内存选项和spark执行器/驱动程序选项无济于事

有没有办法流式传输文件,展平架构,并逐步添加到数据框? JSON的某些行包含前面提到的新字段...因此需要稍后填写。

没有解决方法。 问题在于JVM对象限制。 我最终使用了scala json解析器并手动构建了数据帧。

您可以通过多种方式实现这一目标。

首先在阅读时,您可以提供数据帧的架构来读取json,或者您可以允许spark自己推断架构。

一旦json处于数据框架中,您可以按照以下方法将其展平。

一个。 在数据框架上使用explode()来展平它。 使用spark sql并使用访问嵌套字段。 运营商。 你可以在这里找到例子

最后,如果要向dataframe a添加新列。 第一个选项,使用withColumn()是一种方法。 但是,对于添加的每个新列和整个数据集,都将执行此操作。 使用sql从现有生成新的数据帧 - 这可能是最简单的c。 最后,使用map,然后访问元素,获取旧模式,添加新值,创建新模式并最终获得新df - 如下所示

一个withColumn将在整个rdd上工作。 因此,对于要添加的每个列,通常使用该方法并不是一个好习惯。 有一种方法可以在map函数中处理列及其数据。 由于一个map函数在这里完成工作,因此添加新列及其数据的代码将并行完成。

一个。 您可以根据计算收集新值

将这些新列值添加到main rdd,如下所示

val newColumns: Seq[Any] = Seq(newcol1,newcol2)
Row.fromSeq(row.toSeq.init ++ newColumns)

这里的row,是map方法中行的引用

C。 创建新架构,如下所示

val newColumnsStructType = StructType{Seq(new StructField("newcolName1",IntegerType),new StructField("newColName2", IntegerType))

d。 添加到旧架构

val newSchema = StructType(mainDataFrame.schema.init ++ newColumnsStructType)

使用新列创建新数据框

val newDataFrame = sqlContext.createDataFrame(newRDD, newSchema)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM