Spark SQL 支持两种不同的方法用于转换已存在的 RDD 成为 Dataset。
第一种方法是使用反射去推断一个包含指定的对象类型的 RDD 的 Schema。在你的 Spark 应用程序中当你已知 Schema 时这个基于方法的反射可以让你的代码更简洁。不过这种方法要求你在写程序时已经知道RDD对象的结构信息,因为需要提前根据该结构信息来定义case class。
第二种用于创建 Dataset 的方法是通过一个允许你构造一个 Schema 然后把它应用到一个已存在的 RDD 的编程接口。然而这种方法更繁琐,当列和它们的类型知道运行时都是未知时它允许你去构造 Dataset。该方法适用于在运行之前还不知道列以及列的类型的情况。
使用反射推断 Schema
// Spark SQL 的 Scala 接口支持自动转换一个包含 case classes 的 RDD 为 DataFrame。 Case class 定义了表的 Schema。Case class 的参数名使用反射读取并且成为了列名。
// Case class 也可以是嵌套的或者包含像 SeqS 或者 ArrayS 这样的复杂类型。这个 RDD 能够被隐式转换成一个 DataFrame 然后被注册为一个表。表可以用于后续的 SQL 语句。
import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder
import org.apache.spark.sql.Encoder
// For implicit conversions from RDDs to DataFrames
import spark.implicits._
// Create an RDD of Person objects from a text file, convert it to a Dataframe
val peopleDF = spark.sparkContext
.textFile("examples/src/main/resources/people.txt")
.map(_.split(","))
.map(attributes => Person(attributes(0), attributes(1).trim.toInt))
.toDF()
以编程的方式指定 Schema
当 case class 不能够在执行之前被定义(例如,records 记录的结构在一个 string 字符串中被编码了,或者一个 text 文本 dataset 将被解析并且不同的用户投影的字段是不一样的)。一个 DataFrame 可以使用下面的三步以编程的方式来创建。
- 从原始的 RDD 创建 RDD 的 RowS(行)。
- Step 1 被创建后,创建 Schema 表示一个 StructType 匹配 RDD 中的 Rows(行)的结构。
- 通过 SparkSession 提供的 createDataFrame 方法应用 Schema 到 RDD 的 RowS(行)。
import org.apache.spark.sql.types._
import org.apache.spark.sql.Row
// Create an RDD
val peopleRDD = spark.sparkContext.textFile("examples/src/main/resources/people.txt")
// The schema is encoded in a string
val schemaString = "name age"
// Generate the schema based on the string of schema
val fields = schemaString.split(" ")
.map(fieldName => StructField(fieldName, StringType, nullable = true))
val schema = StructType(fields)
// Convert records of the RDD (people) to Rows
val rowRDD = peopleRDD
.map(_.split(","))
.map(attributes => Row(attributes(0), attributes(1).trim))
// Apply the schema to the RDD
val peopleDF = spark.createDataFrame(rowRDD, schema)
本文章主要参考了http://cwiki.apachecn.org/pages/viewpage.action?pageId=2883736