SparkSQL基础知识及与HIVE整合UDF函数编写

什么是SparkSQL

用于处理结构化数据的Spark模块
可以通过DataFrame和DataSet处理数据

SparkSQL特点

1易整合
可以使用java、scala、python、R等语言的API操作
2统一的数据访问
连接到任何数据源的方式相同。
3 兼容hive
4标准的数据连接(JDBC/ODBC)

SQL 优缺点

优点:表达清晰 ,难度低,已学习
**缺点:**复杂的业业务需要复杂的sql,复杂分析Sql嵌套较多

Hive和SparkSQL对比
Hive是将SQL转化成Mapredue进行计算
SparkSQL转化RDD进行计算
在这里插入图片描述

SparkSQL的两个数据抽象
DataFrame
DataSet

DataFrame :是以RDD为基础的带有Schema元信息的分布式数据集。

(DataFrame=Schema+RDD*n)在这里插入图片描述

DataSeat
含有类型信息的DataFrame就是DataSet
(DataSaet=DataFrame+类型= Schema+RDD*n+类型)
DataSet包含了DataFrame的功能
在这里插入图片描述

SparkSql初体验


//读取数据
val lineRDD= sc.textFile("hdfs://node01:8020/tt.txt").map(_.split(" "))
//实例样例类(类似于表的结构)
case class Person(id:Int, name:String, age:Int)
//遍历数据,将数据填充到样例类中
val personRDD = lineRDD.map(x => Person(x(0).toInt, x(1), x(2).toInt))
//将RDD转换成DataFrame
val personDF = personRDD.toDF
//查看数据
personDF.show
//输出表结构
personDF.printSchema
//将DataFrame注册为张表
personDF.createOrReplaceTempView("t_person")
//通过SQL语句进行查询
spark.sql("select id,name from t_person where id > 3").show

注意
使用SparkSession对象(spark)直接读取数据,读取文本文件是没有元数据信息,读取json文件有元数据信息。

DataSet 创建

第一种

1.通过spark.createDataset创建Dataset
val fileRdd = sc.textFile("hdfs://node01:8020/person.txt") //RDD[String]
val ds1 = spark.createDataset(fileRdd)  //DataSet[String] 
ds1.show

第二种

2.通RDD.toDS方法生成DataSet
case class Person(name:String, age:Int)
val data = List(Person("zhangsan",20),Person("lisi",30)) //List[Person]
val dataRDD = sc.makeRDD(data)
val ds2 = dataRDD.toDS  //Dataset[Person]
ds2.show

第三种

在这里插入代码片

第三种

3.通过DataFrame.as[泛型]转化生成DataSet
case class Person(name:String, age:Long)
val jsonDF= spark.read.json("file:///export/servers/spark/examples/src/main/resources/people.json")
val jsonDS = jsonDF.as[Person] //DataSet[Person]
jsonDS.show

dataSet 进行对表的注册

jsonDS.createOrReplaceTempView("t_person")
spark.sql("select * from t_person").show

SparkSQL两种查询方式

准备工作

val lineRDD= sc.textFile("hdfs://node01:8020/person.txt").map(_.split(" "))
case class Person(id:Int, name:String, age:Int)
val personRDD = lineRDD.map(x => Person(x(0).toInt, x(1), x(2).toInt))
val personDF = personRDD.toDF
personDF.show


DSL风格SparkSQL语句查询
1.查看name字段的数据
personDF.select(personDF.col("name")).show
personDF.select(personDF("name")).show
personDF.select(col("name")).show
personDF.select("name").show

2.查看 name 和age字段数据
personDF.select("name", "age").show
 
3.查询所有的name和age,并将age+1
personDF.select(personDF.col("name"), personDF.col("age") + 1).show
personDF.select(personDF("name"), personDF("age") + 1).show
personDF.select(col("name"), col("age") + 1).show
personDF.select("name","age").show
//personDF.select("name", "age"+1).show 
personDF.select($"name",$"age",$"age"+1).show


4.过滤age大于等于25的,使用filter方法过滤
personDF.filter(col("age") >= 25).show
personDF.filter($"age" >25).show
 
5.统计年龄大于30的人数
personDF.filter(col("age")>30).count()
personDF.filter($"age" >30).count()
 
6.按年龄进行分组并统计相同年龄的人数
personDF.groupBy("age").count().show


SQL风格
在程序中使用spark.sql() 来执行SQL查询,结果将作为一个DataFrame返回
personDF.createOrReplaceTempView(“t_person”)
spark.sql(“select * from t_person”).show

1.显示表的描述信息
spark.sql("desc t_person").show
 
2.查询年龄最大的前两名
spark.sql("select * from t_person order by age desc limit 2").show
 
3.查询年龄大于30的人的信息
spark.sql("select * from t_person where age > 30 ").show
 
4.使用SQL风格完成DSL中的需求
spark.sql("select name, age + 1 from t_person").show
spark.sql("select name, age from t_person where age > 25").show
spark.sql("select count(age) from t_person where age > 30").show
spark.sql("select age, count(age) from t_person group by age").show

总结
1.DataFrame和DataSet都可以通过RDD来进行创建
2.也可以通过读取普通文本创建–注意:直接读取没有完整的约束,需要通过RDD+Schema
3.通过josn/parquet会有完整的约束
4.不管是DataFrame还是DataSet都可以注册成表,之后就可以使用SQL进行查询了! 也可以使用DSL!

创建DataFrame 和DataSet 的三种方式

第1种:指定列名添加Schema 第2种:通过StructType指定Schema 第3种:编写样例类,利用反射机制推断Schema

第一种指定列名添加Schema

import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{
   DataFrame, SparkSession}


object CreateDFDS {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkSession
    val spark: SparkSession = SparkSession.builder().master("local[*]").appName("SparkSQL").getOrCreate()
    val sc: SparkContext = spark.sparkContext
    sc.setLogLevel("WARN")
    //2.读取文件
    val fileRDD: RDD[String] = sc.textFile("D:\\data\\person.txt")
    val linesRDD: RDD[Array[String]] = fileRDD.map(_.split(" "))
    val rowRDD: RDD[(Int, String, Int)] = linesRDD.map(line =>(line(0).toInt,line(1),line(2).toInt))
    //3.将RDD转成DF
    //注意:RDD中原本没有toDF方法,新版本中要给它增加一个方法,可以使用隐式转换
    import spark.implicits._
    val personDF: DataFrame = rowRDD.toDF("id","name","age")
    personDF.show(10)
    personDF.printSchema()
    sc.stop()
    spark.stop()
  }
}

第二种

import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types._
import org.apache.spark.sql.{
   DataFrame, Row, SparkSession}


object CreateDFDS2 {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkSession
    val spark: SparkSession = SparkSession.builder().master("local[*]").appName("SparkSQL").getOrCreate()
    val sc: SparkContext = spark.sparkContext
    sc.setLogLevel("WARN")
    //2.读取文件
    val fileRDD: RDD[String] = sc.textFile("D:\\data\\person.txt")
    val linesRDD: RDD[Array[String]] = fileRDD.map(_.split(" "))
    val rowRDD: RDD[Row] = linesRDD.map(line =>Row(line(0).toInt,line(1),line(2).toInt))
    //3.将RDD转成DF
    //注意:RDD中原本没有toDF方法,新版本中要给它增加一个方法,可以使用隐式转换
    //import spark.implicits._
    val schema: StructType = StructType(Seq(
      StructField("id", IntegerType, true),//允许为空
      StructField("name", StringType, true),
      StructField("age", IntegerType, true))
    )
    val personDF: DataFrame = spark.createDataFrame(rowRDD,schema)
    personDF.show(10)
    personDF.printSchema()
    sc.stop()
    spark.stop()
  }
}

第三种

import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{
   DataFrame, SparkSession}


object CreateDFDS3 {
   
case class Person(id:Int,name:String,age:Int)
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkSession
    val spark: SparkSession = SparkSession.builder().master
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值