Spark SQL and DataFrames
Spark SQL
Spark SQL概述
什么是Spark SQL?
SparkSQL是spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrames,并且作为分布式SQL查询引擎的作用。
为什么要学SparkSQL?
SparkSQL将Spark SQL转换为RDD,然后提交到集群执行,执行效率非常快,比如hive是将hive SQL转换为MapReduce然后提交到集群上执行,大大简化了编写程序的复杂性。
总结:
- SparkSQL是Spark上的高级模块,SparkSQL是一个SQL解析引擎,将SQL解析成特殊的RDD(DataFrame),然后在Spark集群中运行。
- SparkSQL是用来处理结构化数据的(先将非结构化的数据转换成结构化数据)
- SparkSQL支持两种编程API 1.SQL方式 2.DataFrame的方式(DSL)
- SparkSQL兼容hive(元数据库、SQL语法、UDF、序列化、反序列化机制)
- SparkSQL支持统一的数据源,课程读取多种类型的数据
- SparkSQL提供了标准的连接(JDBC、ODBC),以后可以对接一下BI工具
参考:http://spark.apache.org/sql/
SparkSQL特点:
- Integraied:易整合,SparkSQL允许SQL、DataFrame API访问数据。
- Union Data Access:统一的数据访问方式,提供了访问各种数据源的通用方法,包括Hive、Avro、Parquet、ORC、JSON和JDBC。
- Hive Integration:兼容hive,支持HiveQL语法以及HiveSerDes和UDF。
- Standard Connectivity:标准的数据连接,支持标准连接(JDBC、ODBC)
DataFrames
什么是DataFrames?
与RDD类似,DataFrames也是一个分布式数据容器,但DataFrames更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即schema。它是抽象的数据集,放的都是描述信息,DataFrames是一个特殊的RDD。好处:可以使用SQL语句,带来编码上的方便,降低了spark的使用难度。
在Spark中,DataFrame是一种按列组织的分布式数据集,概念上等价于关系数据库中一个表或者是Python中的data frame,但是在底层进行了更丰富的优化。
DataFrame与RDD对比
RDD和DataFrame的区别:
DataFrame里面存放的结构化数据的描述信息,DataFrame要有表头(表的描述信息),描述了有多少列,每一列数叫什么名字、什么类型、能不能为空
DataFrame是特殊的RDD(RDD+Schema信息就变成了DataFrame)DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。
与RDD的主要区别在于:前者带有Schema元数据,即DataFrame所表示的二维数据集的每一列都有名称和类型。
由于无法知道RDD数据集内部的结构,Spark执行作业只能在调度阶段进行简单通用的优化,而DataFrame带有数据集内部的结构,可以根据这些信息进行针对性的优化,最终实现优化运行效率。
DataFrame带来的好处:
- 精简代码
- 提升执行效率
- 减少数据读取:忽略无关数据,根据查询条件进行适当裁剪。
DataFrame使用
Spark SQL支持两种方式来将RDD转换为DataFrame。
第一种方式,是使用反射来推断包含了特定数据类型的RDD的元数据。这种基于反射的方式,代码比较简洁,当你已经知道你的RDD的元数据时,是一种非常不错的方式。
第二种方式,是通过编程接口来创建DataFrame,你可以在程序运行时动态构建一份元数据,然后将其应用到已经存在的RDD上。这种方式的代码比较冗长,但是如果在编写程序时,还不知道RDD的元数据,只有在程序运行时,才能动态得知其元数据,那么只能通过这种动态构建元数据的方式。
创建DataFrames
在Spark SQL中sqlContext是创建Sql的入口
在1.6.x前入口为sqlContext,2.x后入口为SparkSession。
4种:
结构化数据文件、hive表、外部表、已经存在的RDDs
存在的RDDs:
反射、编程(2种)
1.6.x
在1.x的基础上,由普通的RDD转化成DataFrame,然后执行SQL,具体步骤如下:
1.创建sparkContext,然后再创建SQLContext
2.先创建RDD,对数据进行整理,然后关联case class,将非结构化数据转换成结构化数据
3.显示的调用toDF方法将RDD转换成DataFrame
4.注册临时表
5.执行SQL(Transformation,lazy)
6.执行Action
case class就定义了元数据。Spark SQL会通过反射读取传递给case class的参数的名称,然后将其作为列名。
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.10</artifactId>
<version>1.6.1</version>
</dependency>
使用反射推断Schema在已有的RDD创建:
import org.apache.spark.sql.SQLContext
import org.apache.spark.{SparkConf, SparkContext}
//使用反射的方式,把RDD转化为DataFrame
object RDDtoDf {
def main(args: Array[String]): Unit = {
//创建RDD
val sparkConf = new SparkConf().setAppName("sparkSqlDemo").setMaster("local")
val sc = new SparkContext(sparkConf)
//创建sparksql的入口
val sqlContext = new SQLContext(sc)
val linesrdd = sc.textFile("C:\\Users\\brz\\Desktop\\数据\\person.txt")
//把RDD关联schema(case class)
val personRDD = linesrdd
.map(line => {
val fields = line.split(",")
val id = fields(0).toLong
val name = fields(1)
val age = fields(2).toInt
val faceValue = fields(3).toDouble
Person(id, name, age, faceValue)
})
//转换RDD=>DataFrame
//导入隐式转换
import sqlContext.implicits._
val df = personRDD.toDF()
//使用SQL
//把DataFrame注册成一张临时表
df.registerTempTable("t_person")
//执行SQL语句
val res = sqlContext.sql("select * from t_person")
//查看结果
res.show()
sc.stop()
}
}
//定义case class(相当于表的schema)
case class Person(id:Long,name:String,age:Int,faceValue:Double)
通过StructType直接指定Schema编程创建:
1.创建sparkContext,然后再创建SQLContext
2.先创建RDD,对数据进行整理,然后关联Row,将非结构化数据转换成结构化数据
3.定义schema
4.调用sqlContext的createDataF