Spark SQL - 隐式创建模式的精确差异&编程

时间:2016-01-30 20:47:24

标签: apache-spark apache-spark-sql

我试图理解确切的区别,哪个方法可以用于创建模式隐式和优先之间的特定场景。编程。

在Databricks网站上,这些信息并不那么精彩。说明

我们可以看到,当使用Reflection(隐式RDD到DF)方式时,我们可以通过使用Map函数从文本文件中选择特定列来创建Case类。

在Programmatic Style中 - 我们正在为数据集加载一个文本文件(类似于反射)

创建SchemaString(String)=“知道文件,我们可以指定我们需要的列”(类似于反射方式的案例类)

导入ROW API - 它将再次映射到特定列& Schema String中使用的数据类型(类似于案例类)

然后我们创建DataFrame&在这之后一切都是一样的.. 那么这两种方法的确切区别是什么呢?

http://spark.apache.org/docs/1.5.2/sql-programming-guide.html#inferring-the-schema-using-reflection

http://spark.apache.org/docs/1.5.2/sql-programming-guide.html#programmatically-specifying-the-schema

请解释......

2 个答案:

答案 0 :(得分:1)

生成的模式是相同的,所以从这个角度来看,没有区别。在这两种情况下,您都在为数据提供架构,但在一种情况下,您可以从案例类中执行此操作,而在另一种情况下,您可以使用集合,因为架构构建为{{ 1}}。 所以它基本上是元组和集合之间的选择。我看到它的方式,最大的区别是案例类必须在代码中,而以编程方式指定架构可以在运行时完成,因此您可以,例如,您可以基于另一个DataFrame构建一个架构。在运行时重读。 作为一个例子,我写了一个通用的工具来" nest"数据,从CSV读取,以及将一组带前缀的字段转换为结构数组。 由于该工具是通用的,并且模式仅在运行时已知,因此我使用了编程方法。 另一方面,通过反射对代码进行编码通常更容易,因为您不必处理所有StructType(Array[StructField])个对象,因为它们来自蜂巢Metastore,其数据类型具有要映射到你的scala类型。

答案 1 :(得分:0)

以编程方式指定架构 如果无法提前定义案例类(例如,记录的结构以字符串形式编码,或者文本数据集将被解析,字段将针对不同的用户进行不同的投影),则可以通过三个步骤以编程方式创建DataFrame

从原始RDD创建行的RDD; 创建由与步骤1中创建的RDD中的行结构匹配的StructType表示的模式。 通过SQLContext提供的createDataFrame方法将架构应用于行的RDD。

例如:

// sc is an existing SparkContext.
val sqlContext = new org.apache.spark.sql.SQLContext(sc)

// Create an RDD
val people = sc.textFile("examples/src/main/resources/people.txt")

// The schema is encoded in a string
val schemaString = "name age"

// Import Row.
import org.apache.spark.sql.Row;

// Import Spark SQL data types
import org.apache.spark.sql.types.{StructType,StructField,StringType};

// Generate the schema based on the string of schema
val schema =
  StructType(
    schemaString.split(" ").map(fieldName => StructField(fieldName, StringType, true)))

// Convert records of the RDD (people) to Rows.
val rowRDD = people.map(_.split(",")).map(p => Row(p(0), p(1).trim))

// Apply the schema to the RDD.
val peopleDataFrame = sqlContext.createDataFrame(rowRDD, schema)

// Register the DataFrames as a table.
peopleDataFrame.registerTempTable("people")

使用反射推断架构 Spark SQL的Scala接口支持自动将包含RDD的案例类转换为DataFrame。 case类定义表的模式。使用反射读取case类的参数名称,并成为列的名称。案例类也可以嵌套或包含复杂类型,如序列或数组。此RDD可以隐式转换为DataFrame,然后注册为表。表可以在后续的SQL语句中使用。

例如:

// sc is an existing SparkContext.
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
// this is used to implicitly convert an RDD to a DataFrame.
import sqlContext.implicits._

// Define the schema using a case class.
// Note: Case classes in Scala 2.10 can support only up to 22 fields. To work around this limit,
// you can use custom classes that implement the Product interface.
case class Person(name: String, age: Int)

// Create an RDD of Person objects and register it as a table.
val people = sc.textFile("examples/src/main/resources/people.txt").map(_.split(",")).map(p => Person(p(0), p(1).trim.toInt)).toDF()
people.registerTempTable("people")