Spark SQL DataFrame与DataSet
DataFrame
DataFrame是一种带有Schema元信息的分布式数据集。类似于传统数据库的二维表,定义有字段名称和类型,用户可以像操作数据库表一样使用DataFrame
DataFrame在1.3.0版本之前,称为SchemaRDD,存放Row对象的RDD,每个Row对象代表一行记录。
DF创建方式
-
通过createDataFrame() 加载内部数据构建DF
a. 将Seq[]集合转化为DataFrame
b. 将RDD[Product]数据集转化为DataFrame,RDD[Product]一般为“case classes”或“tuples”
case class Person(name:String,age:Int,address:String);
val rdd = session.sparkContext.textFile("file:///F:\\测试数据\\users.txt")
val rdd1 = rdd.map(x=>x.split(" ")).map(x=>(x(0),x(1),x(2))) //tuples
或
val rdd1 = rdd.map(x=>x.split(" ")).map(x=>new Person(x(0),x(1).toInt,x(2))) //case classes
val _person_df_rdd = session.createDataFrame(rdd1)
_person_df_rdd.show()
-
通过SparkSession的read加载外部数据源
说明:通过session.read加载外部不同数据源,包括:json、orc、parquet、csv、file等等。
val _df = session.read.text("file:///F:\\测试数据\\users.txt")
- 通过隐式类型转换,直接将Scala中的集合转为DF
val session1 = SparkSession.builder().master("local[2]").appName("DF").getOrCreate()
import session1.implicits._
val _person = List(("zhangsan",12),("lilei",23),("hanmeumei",34))
val _person_df = _person.toDF()
DataSet
DataSet是一个特定域的强类型的不可变数据集,每个DataSet都有一个非类型化视图DataFame(DataFame是DataSet[Row]的一种表现形式)。
创建DataSet需要显式提供Encoder把对象序列化为二进制形式进行存储,而不是使用Java序列化或者Kryo序列化
DataSet使用专门的编译器序列化对象在网络间传输处理。编译器动态生成代码,可以在编译的时候检查类型,不需要将对象反序列化就可以进行过滤、排序等操作,避免了Shuffle过程中频繁的序列化和反序列化,有效减少了内存的使用和Java对象频繁GC的开销。
RDD、DataFrame和DataSet三者之间差异
RDD[Person]----(case反射机制)-------DataFrame[ROW]--------------------------DataSet[Person]
Pesron ROW[“name”,“age”,“address”] {Person:(“name”,“age”,“address”)}
Pesron ROW[“name”,“age”,“address”] {Person:(“name”,“age”,“address”)}
Pesron ROW[“name”,“age”,“address”] {Person:(“name”,“age”,“address”)}
Pesron ROW[“name”,“age”,“address”] {Person:(“name”,“age”,“address”)}
Pesron ROW[“name”,“age”,“address”] {Person:(“name”,“age”,“address”)}
Pesron ROW[“name”,“age”,“address”] {Person:(“name”,“age”,“address”)}
三者之间相互转换:
a.RDD–>DataFrame SparkSession.createDataFrame()
b.RDD–>DataSet SparkSession.createDataSet()
c.DF,DS–>RDD DF.rdd–>RDD[ROW];DS,rdd–>RDD[Person]
d.DataFrame–>DataSet SparkSession.createDataSet(DF.rdd)–> DataSet[ROW]
e.DataSet–>DataFrame DS.toDF()