目录
SparkSQL
一、什么是SparkSQL?
二、Spark SQL的特点
DataFrame
一、什么是DataFrame?
二、创建DataFrame
三、使用DSL语句和SQL语句操作DataFrame
1、DSL语句
2、SQL
四、临时视图(Temporary View)
1、什么是视图?
2、类型
3.创建与使用视图
数据集(DataSet)
创建和使用DataSet
Spark SQL是Spark的一个模块,用于处理结构化的数据,它提供了一个数据抽象DataFrame并且作为分布式SQL查询引擎的作用。
Spark SQL就是将SQL转换成一个任务,提交到集群上运行,类似于Hive的执行方式。
1.Spark SQL已经集成在Spark中
2.提供了统一的数据访问方式:JSON、CSV、JDBC、Parquet等都是使用统一的方式进行访问
3.兼容Hive
4.支持标准的数据连接:JDBC、ODBC
DataFrame是组织成命名列的数据集。它在概念上等同于关系数据库中的表,但在底层具有更丰富的优化。关系型数据库中的表由表结构和数据组成,而DataFrame也类似,由schema(结构)和数据组成,其数据集是RDD。DataFrame可以从各种来源构建,如结构化的数据文件(csv)、Hive中的数据、外部数据库或者现有的RDD。DataFrame API支持的语言有Java、Scala、Python和R。
创建DataFrame有三种方法:使用样本类,使用SparkSession以及通过带有格式的数据文件(JSON)来创建
测试数据
员工表 字段说明
部门编号 empno:Int,
员工名 ename:String,
职位 job:String,
经理 mgr:String,
入职日期 hiredate:String,
工资 sal:Int,
奖金 comm:String,
部门编号 deptno:Int
1.使用样本类创建DataFrame
(1)创建一个样本类用来存储员工表的结构
case class Emp(empno:Int,ename:String,job:String,mgr:String,hiredate:String,sal:Int,comm:String,deptno:Int)
(2)通过sc导入emp.csv,并且根据分隔符来做切分
val line=sc.textFile("hdfs://centos:9000/emp.csv").map(_.split(","))
(3)将数据和表结构关联起来
val emp=line.map(x=>Emp(x(0).toInt,x(1),x(2),x(3),x(4),x(5).toInt,x(6),x(7).toInt))
(4)根据上面通过样本类实例化的对象生成DataFrame
val empDF =emp.toDF
(5)然后就可以通过命令来对表内容和表结构进行查看了
2.使用SparkSession创建DataFrame
SparkSession是Spark新的访问接口(统一的访问方式),用来访问Spark的各个模块
(1)通过Sparkcontext导入数据
val emp=sc.textFile("hdfs://centos:9000/emp.csv").map(_.split(","))
(2)使用structType建立表结构(schema)
import org.apache.spark.sql._
import org.apache.spark.sql.types._
val myschema = StructType(List(
StructField("empno",DataTypes.IntegerType),
StructField("ename",DataTypes.StringType),
StructField("job",DataTypes.StringType),
StructField("mgr",DataTypes.StringType),
StructField("hiredate",DataTypes.StringType),
StructField("sal",DataTypes.IntegerType),
StructField("comm",DataTypes.StringType),
StructField("deptno",DataTypes.IntegerType)
))
(3)使用map方法将每一行的数据映射成Row类型的对象,使用SparkSession建立DataFrame
val rowRDD = emp.map(x=>Row(x(0).toInt,x(1),x(2),x(3),x(4),x(5).toInt,x(6),x(7).toInt))
val df=spark.createDataFrame(rowRDD,myschema)
3.通过带有格式的数据文件(JSON)来创建DataFrame
val empDF = spark.read.json("hdfs://centos:9000/emp.json")
使用上面创建的表作为示例
查询所有的员工信息:df.show
查询员工信息:姓名:df.select($"ename").show
查询员工信息:姓名、薪水、薪水+100:df.select($"ename",$"sal",$"sal"+100).show
查询工资大于2000的员工:df.filter($"sal" > 2000).show
分组统计各部门员工人数:df.groupBy($"deptno").count.show
注意:需要将DataFrame注册成一个视图(表)
创建视图:df.createOrReplaceTempView("emp")
通过标准SQL语句进行查询:spark.sql("select * from emp").show
spark.sql("select * from emp where deptno=10").show
spark.sql("select deptno,sum(sal) from emp group by deptno").show
视图是一个虚表,跟RDBMS里的概念是一样的,视图基于实际的表而存在,其实质是一系列的查询语句
局部视图(Temoporary View):只在当前会话中有效,如果创建它的会话终止,则视图也会消失。
全局视图(Global Temporary View): 在全局范围内有效,不同的Session中都可以访问,生命周期是Spark的Application运行周期,全局视图会绑定到系统保留的数据库global_temp中,因此使用它的时候必须加上相应前缀。
创建视图
df.createOrReplaceTempView("emp")
df.createOrReplaceGlobalTempView("empG")
在当前的会话中,两种视图都是可以正常进行查询的
spark.sql("select * from emp").show
spark.sql("select * from global_temp.empG").show
开启一个新的会话对两个视图分别进行查询
spark.newSession.sql("select * from emp").show -----> 报错,Table or View Not Found
spark.newSession.sql("select * from global_temp.empG").show ---->可以正常查询
数据集与RDDs类似,它们不是使用Java序列化或Kryo,而是使用专门的编码器序列化对象,以便通过网络进行处理或传输。虽然编码器和标准序列化负责将对象转换为字节,但编码器是动态生成的代码,并使用允许Spark执行许多操作(如过滤、排序和哈希)的格式,而无需将字节反序列化为对象。
1、方式一:使用序列
测试数据:(1,"Tom") (2,"Mary")
(1)定义case class
case class MyData(a:Int,b:String)
(2)使用序列创建DataSet
val DS = Seq(MyData(1,"Tom"),MyData(2,"Mary")).toDS
2、方式二:通过case class作为编码器,将DataFrame转换成DataSet
(1)定义case class
case class Person(name:String,age:BigInt)
(2)读入JSON的数据
val df = spark.read.json("/root/temp/people.json")
(3)将DataFrame转换成DataSet
val PersonDS =df.as[Person]
3、方式三:读取HDFS的数据文件
测试文件data.txt内容
I love Beijing
I love China
Beijing is the capital of China
(1)读取HDFS的文件,直接创建DataSet
val lineDS = spark.read.text("hdfs://bigdata111:9000/input/data.txt").as[String]
(2)分词操作,查询长度大于3的单词
val words = lineDS.flatMap(_.split(" ")).filter(_.length > 3)
words.show
words.collect