### SparkSQL的内置函数(重点)
导入:import org.apache.spark.sql.funcations._
Action
df1.count
// 缺省显示20行
df1.union(df1).show()
// 显示2行
df1.show(2)
// 不截断字符
df1.toJSON.show(false)
// 显示10行,不截断字符
df1.toJSON.show(10, false)
// collect返回的是数组, Array[org.apache.spark.sql.Row]
val c1 = df1.collect()
// collectAsList返回的是List, List[org.apache.spark.sql.Row]
val c2 = df1.collectAsList()
// 返回 org.apache.spark.sql.Row
val h1 = df1.head()
val f1 = df1.first()
// 返回 Array[org.apache.spark.sql.Row],长度为3
val h2 = df1.head(3)
val f2 = df1.take(3)
// 返回 List[org.apache.spark.sql.Row],长度为2
val t2 = df1.takeAsList(2)
Transformations
// map、flatMap操作(与RDD基本类似)
df1.map(row=>row.getAs[Int](0)).show
case class Peoples(age:Int, names:String)
val seq1 = Seq(Peoples(30, "Tom, Andy, Jack"), Peoples(20, "Pand, Gate, Sundy"))
val ds1 = spark.createDataset(seq1)
val ds2 = ds1.map(x => (x.age+1, x.names))
ds2.show
val ds3 = ds1.flatMap{ x =>
val a = x.age
val s = x.names.split(",").map(name => (a, name.trim))
s
}
ds3.show
// filter
df1.filter("sal>3000").show
Spark的两种操作风格(重点)
SQL风格:这种风格和咱们操作MySQL、Hive的语句比较类似,而且写起来也比较简单易懂,同时SQL风格完全支持MySQL的语法结构,并且也可以使用自定义UDF。
使用方式:通过SQLContext对象来去使用SQL方法,将SQL放入方法内,进行运行
例如:sqlContext.sql(“select date,sum(memory) from user group by date”).show()
DSL(Domain Specific Language)风格:DSL风格属于Spark的特定领域语法,可以将SQL风格内的关键字,拆解,单独使用,这种方式操作比较灵活,比较适合逻辑比较复杂的业务场景。
使用方式:通过DF进行方法调用,直接使用
例如:df.groupBy(col(“date”)).agg(sum(“memory”)).show()
SparkSession创建方式
private val session: SparkSession = SparkSession.builder().config(conf).getOrCreate()
Spark的开窗函数
row_number() over()
rank() over()
dense_rank() over()
DataSet (重点)
Dataset-1.6版本后推出的全新特性
Dataset = RDD[case class].toDS
1、Dataset和DataFrame拥有完全相同的成员函数,区别只是每一行的数据类型不同;
2、DataFrame 定义为 Dataset[Row]。每一行的类型是Row,每一行究竟有哪些字段,各个字段又是什么类型都无从得知,只能用前面提到的getAS方法或者模式匹配拿出特定字段;
3、Dataset每一行的类型都是一个case class,在自定义了case class之后可以很自由的获得每一行的信息;
DataSet分为强弱类型
强类型:使用case class这种方式,自己确定类型,叫强类型(表现形式强)
弱类型:使用统一的Row来封装类型参数,这个时候,你在取值的时候,很难发现数据类型(表现形式弱)
三者之间的转换:
DataFrame/Dataset 转 RDD:
df.rdd.foreach(row=> println(row.getAs[String](0)))
ds.rdd.foreach(println)
RDD转换为DataFrame:
要导入隐式转换
rdd.toDF()
RDD 转 Dataset:
要导入隐式转换
核心是 需要设置样例类的类型 使用case class方式进行转换操作
rdd.toDS()
Dataset 转 DataFrame:
可以将DS封装的case class转换为Row
ds.toDF
DataFrame 转 Dataset:
将DF转换为DS,需要设置case class
df.as[Coltest2]
三者之间创建临时表或者视图的方法
ds2.createOrReplaceTempView() // 如果当前的临时视图存在,那么将其覆盖
ds2.createTempView() // 创建临时视图
df.registerTempTable() // DF老版本创建临时表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jIHqjt8x-1573745332081)(1573541030185.png)]
自定义函数(UDF)(重点)
自定义函数,其实是根据自己的业务,设置函数的条件,如果当前Spark中没有相关的条件函数,那么我们就必须要自定义一个函数,来解决我们的业务开发问题。
使用方式:
首先创建函数(方法),注册当前的函数,如果是方法的话,需要转换成函数,使用函数(放在SQL里面进行使用),我们在注册函数的时候,那么需要设置函数名
UDAF(了解)
案例:
需求:
- 统计每天每个搜索词用户访问量降序排序
- 最后输出结果为(‘日期_搜索词’,UV)
- 统计分析时候,我会给你匹配词库,根据匹配词库,进行匹配符合规则的数据,不符合将其过滤
val queryFilter = Map(
"city"-> List("beijing"),
"platform"->List("android"),
"version" -> List("1.0")
)
可以使用RDD进行过滤操作,但是最终统计结果必须用SQL(DSL)