Spark SQL 是Spark用于结构化数据(structured data)处理的Spark模块
Hive:基于Hadoop的SQL引擎工具,目的是为了简化MapReduce的开发,提高开发效率,可以把SQL转化成MapReduce程序(因为大数据统计用的是新的代码方式)
Spark SQL 的前身是Shark,受Hive发展的制约
Shark分为SparkSQL(兼容Hive)和Hive on Spark(计划将Spark作为Hive的底层引擎之一)
SparkSQL为了简化RDD的开发
写SQL语句时底层会自动把它转化成RDD
特点:
- 易整合
无缝整合了SQL查询核Spark编程 - 通用性
用相同的方式连接不同的数据源 - 兼容Hive
- 标准数据连接
通过JDBC或者ODBC来连接
DataFrame,DataSet,RDD 都有分区的概念
DataFrame和DataSet 有完全相同的成员函数,区别只是每一行的数据类型不同
DataFrame其实是DataSet的一个特例 type DataFrame=DataSet[Row]
DataSet----->DataFrame----->RDD
DataFrame
DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格
RDD更关注数据,DataFrame更关注数据的结构
RDD:
Person()
DataFrame:
Name | Age | Height |
String | int | Double |
DataFrame也是懒执行,但性能比RDD高
原因:底层执行一些优化策略
读取Json文件
val dr=spark.read.json("/home/wwx/桌面/user.json")
dr中的内容
dr: org.apache.spark.sql.DataFrame = [age: bigint, username: string]
显示数据
dr.show
输出
+---+--------+
|age|username|
+---+--------+
| 30|zhangsan|
| 20|zhangsan|
| 40|zhangsan|
+---+--------+
生成临时表
df.createTempView("user")
执行sql语句
简化了RDD
DataFrameAPI允许我们使用DataFrame而不用去注册临时表或者生成SQL表达式。DataFrameAPI既有transformation操作也有action操作
SparkSession是创建DataFrame和执行Sql的入口
创建DataFrame有三种方式:
- 通过Spark的数据源进行创建
- 从一个存在的RDD转换
- 从HiveTable进行查询返回
- 通过Spark数据源创建
tip:如果从内存中读取数据,Spark知道数据类型具体是什么。如果是数字,默认为Int;但是如果从文件中读取数据,不确定类型,所以用bigint接收,可以和Long类型转换,不能和Int转换。
- 读取Json文件创建DataFrame
df.createOrReplaceTempView("user")
- 对DataFrame创建一个临时表 (View 只能查询,不能修改)
spark.sql("select avg(age) from user").show()
- 查询
spark.sql("select avg(age) from user").show()
创建全局范围的表
df.createOrReplaceGlobalTempView("user")
//global_temp前缀
spark.sql("select * from global_temp.user").show
DSL语法
不用创建临时视图
tip:涉及到运算时,每列必须使用$,或者采用引号表达式:单引号+字段名
df.select("age")
df.select($"age"+1)// $表示引用
df.select('age+1)
df.filter('age>23) // filter过滤
df.groupBy("age").count.show //
- RDD转换为DataFrame
tip:由于是在内存中,类型确定
- 先创建RDD
val rdd=sc.makeRDD(List(1,2,3,4))
- 转换为DataFrame
val df=rdd.toDF("id") //二维数组,赋予列名
- 变回RDD
df.rdd
//去掉列名,变成行ROW
res17: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = MapPartitionsRDD[42]
DataSet(最方便)
DataSet是分布式弹性数据集,是对DataFrame的一个扩展,加入了类型,更关注类型本身
也是惰性加载
把一行的数据当做一个对象
list.toDS
//DataFrame到DataSet,给他一个类型
case class Emp(age:Long,username:String)
val ds=df.as[Emp]//as[案例类]
//DataSet到DataFrame,去掉类型,保留结构
ds.toDF
//RDD到DS,前提,RDD里是案例类
rdd.toDS
//DS到RDD
ds.rdd