本文作为Spark SQL的第二篇文章,主要讲述一下RDD、DataFrame/DataSet之间的关系及相互转换。
文章主要从以下几个方面进行阐述:
1、Spark中的模块
2、什么是DataFrame
3、RDD和DataFrame的区别
4、什么是DataSet
5、RDD和Dataset的区别
6、Dataset和DataFrame的区别与联系
7、DataSet的创建
8、RDD转DataFrame原因及方式
9、DataFrame转RDD原因及方式
1、Spark中的模块
上图展示了Spark的模块及各模块之间的关系,底层是Spark-core核心模块,Spark每个模块都有一个核心抽象,Spark-core的核心抽象是RDD,Spark SQL等都基于RDD封装了自己的抽象,在Spark SQL中是DataFrame/DataSet。相对来说RDD是更偏底层的抽象,DataFrame/DataSet是在其上做了一层封装,做了优化,使用起来更加方便。从功能上来说,DataFrame/DataSet能做的事情RDD都能做,RDD能做的事情DataFrame/DataSet不一定能做。
2、什么是DataFrame
在Spark中,DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。
3、RDD和DataFrame的区别
DataFrame与RDD的主要区别在于,DataFrame带有schema元信息,即DataFrame所表示的二维表数据集的每一列都带有名称和类型。使得Spark SQL得以洞察更多的结构信息,从而对藏于DataFrame背后的数据源以及作用于DataFrame之上的变换进行了针对性的优化,最终达到大幅提升运行时效率的目标。
RDD,由于无从得知所存数据元素的具体内部结构,Spark Core只能在stage层面进行简单、通用的流水线优化。 DataFrame底层是以RDD为基础的分布式数据集,和RDD的主要区别的是:RDD中没有schema信息,而DataFrame中数据每一行都包含schema
DataFrame = RDD[Row] + shcema
4、什么是DataSet
Dataset是一个由特定领域的对象组成强类型(typedrel)集合,可以使用函数(DSL)或关系运算(SQL)进行并行的转换操作。 每个Dataset 还有一个称为“DataFrame”的无类型(untypedrel)视图,它是[[Row]]的数据集。
5、RDD和Dataset的区别
Dataset与RDD类似,但是,它们不使用Java序列化或Kryo,而是使用专用的Encoder编码器来序列化对象以便通过网络进行处理或传输。虽然Encoder编码器和标准序列化都负责将对象转换为字节,但Encoder编码器是动态生成的代码,并使用一种格式,允许Spark执行许多操作,如过滤,排序和散列,而无需将字节反序列化为对象
6、Dataset和DataFrame的区别与联系
区别:
- Dataset是强类型typedrel的,会在编译的时候进行类型检测;而DataFrame是弱类型untypedrel的,在执行的时候进行类型检测;
- Dataset是通过Encoder进行序列化,支持动态的生成代码,直接在bytes的层面进行排序,过滤等的操作;而DataFrame是采用可选的java的标准序列化或是kyro进行序列化
联系:
- 在spark2.x,DataFrame和Dataset的api进行了统一
- 在语法角度,DataFrame是Dataset中每一个元素为Row类型的特殊情况
type DataFrame = Dataset[Row] - DataFrame和Dataset实质上都是一个逻辑计划,并且是懒加载的,都包含着scahema信息,只有到数据要读取的时候,才会将逻辑计划进行分析和优化,并最终转化为RDD
- 二者由于api是统一的,所以都可以采用DSL和SQL方式进行开发,都可以通过sparksession对象进行创建或者是通过transform转化操作得到
7、DataSet的创建
DataSet的创建在上一篇文章《Spark SQL入门详解》中已经介绍。更多信息可以参见官方文档:
http://spark.apache.org/docs/2.2.1/sql-programming-guide.html#creating-datasets
8、RDD转DataFrame原因及方式
可以将RDD转成DataFrame之后,借用sparksql和sql以及HQL语句快速方便的使用sql语句统计和查询,比如说分组排名(row_number() over()) 分析函数和窗口函数去实现占比分析。
将RDD转化为DataFrame有两种方式:
方式一:通过反射推断schema 要求:RDD的元素类型必须是case class
方式二、编程指定schema 要求:RDD的元素类型必须是Row 自己编写schema(StructType) 调用SparkSession的createDatafrmame(RDD[Row],schema)
9、DataFrame转RDD原因及方式
- 解决一些使用sql难以处理的统计分析
- 将数据写入Mysql
a.DataFrame的write.jdbc,仅支持四种模式:append、overwrite、ignore、default
b.使用rdd的话,除了上述以外还支持insert 和 update操作,还支持数据库连接池 (自定 义,第三方:c3p0 hibernate mybatis)方式,批量高效将大量数据写入 Mysql
方式: DataFrame转换为RDD相对来说比较简单,只需要调用DataFrame的RDD算子即可。