在Spark中为1500列的表定义DataFrame Schema

时间:2017-01-23 04:14:44

标签: apache-spark dataframe apache-spark-sql

我在SQL Server中有一个包含大约1500列的表。我需要从该表中读取数据,然后将其转换为正确的数据类型格式,然后将记录插入Oracle DB。

为表中包含超过1500列的此类表定义架构的最佳方法是什么。除了对列名称和数据类型进行硬编码之外还有其他选择吗?

  1. 使用Case class
  2. 使用StructType
  3. 使用的Spark版本是1.4

3 个答案:

答案 0 :(得分:4)

针对此类要求。我提供case课程方法来准备数据框

是的,有一些限制,如产品性,但我们可以克服... 你可以像下面的例子那样做<版本2.11:

准备一个案例类extends Product并覆盖方法。

喜欢......

  • productArity():Int:返回属性的大小。在我们的例子中,它是33.所以,我们的实现看起来像这样:

  • productElement(n:Int):Any:给定索引,返回属性。作为保护,我们还有一个默认情况,会引发IndexOutOfBoundsException异常:

  • canEqual (that:Any):Boolean:这是三个函数中的最后一个,当对类进行相等性检查时,它作为边界条件:

另一种选择:

使用StructType定义架构并创建数据框。(如果您不想使用spark csv api

答案 1 :(得分:3)

读取包含1500列的表的选项

  

1)使用Case类

案例类不起作用,因为它仅限于22个字段(对于scala版本< 2.11)。

  

2)使用StructType

您可以使用StructType定义架构并创建数据框。

第三个选项

您可以使用Spark-csv包。在此,您可以使用.option("inferschema","true")。这将自动从文件中读取架构。

答案 2 :(得分:1)

您可以使用json格式包含数百个列的架构。然后你可以阅读这个json文件来构建自定义模式。

例如, 你的架构json是:

[
    {
        "columnType": "VARCHAR",
        "columnName": "NAME",
        "nullable": true
    },
    {
        "columnType": "VARCHAR",
        "columnName": "AGE",
        "nullable": true
    },
    .
    .
    .
]

现在您可以读取json以将其解析为某个case类以形成StructType。

case class Field(name: String, dataType: String, nullable: Boolean)

您可以创建一个Map,使其具有与json模式中的Type Type Oracle字符串相对应的spark DataType。

val dataType = Map(
   "VARCHAR" -> StringType,
   "NUMERIC" -> LongType,
   "TIMESTAMP" -> TimestampType,
   .
   .
   .
)

def parseJsonForSchema(jsonFilePath: String) = {
   val jsonString = Source.fromFile(jsonFilePath).mkString
   val parsedJson = parse(jsonString)
   val fields = parsedJson.extract[Field]
   val schemaColumns = fields.map(field => StructField(field.name, getDataType(field), field.nullable))
   StructType(schemaColumns)
}