Spark之SparkSQL实战

DataFrames 基本操作和 DSL SQL风格 UDF函数 以及数据源:

SparkSQL查询

Json数据准备

1
2
3
{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}
1
2
3
4
5
val df =spark.read.json("/input/sparksql/json/people.json")
df.show()
df.filter($"age">21).show();
df.createOrReplaceTempView("person")
spark.sql("SELECT * FROM person").show()

IDEA创建SparkSQL程序

1
2
3
4
5
6
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.1.1</version>
<scope>provided</scope>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.hph.sql

import org.apache.spark.sql.SparkSession


object HelloWorld {

def main(args: Array[String]) {
//创建SparkConf()并设置App名称

val spark = SparkSession
.builder()
.appName("Spark SQL basic example")
.config("spark.some.config.option", "some-value")
.master("local[*]")
.getOrCreate()

// For implicit conversions like converting RDDs to DataFrames
import spark.implicits._

val df = spark.read.json("F:\\spark\\examples\\src\\main\\resources\\people.json")

// Displays the content of the DataFrame to stdout
df.show()

df.filter($"age" > 21).show()

df.createOrReplaceTempView("persons")

spark.sql("SELECT * FROM persons where age > 21").show()

spark.stop()
}
}

SparkSession

老的版本中,SparkSQL提供两种SQL查询起始点,一个叫SQLContext,用于Spark自己提供的SQL查询,一个叫HiveContext,用于连接Hive的查询,SparkSession是Spark最新的SQL查询起始点,实质上是SQLContext和HiveContext的组合,所以在SQLContext和HiveContext上可用的API在SparkSession上同样是可以使用的。SparkSession内部封装了sparkContext,所以计算实际上是由sparkContext完成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.apache.spark.sql.SparkSession


object HelloWorld {

def main(args: Array[String]) {
//创建SparkConf()并设置App名称

val spark = SparkSession
.builder()
.appName("Spark SQL basic example")
.config("spark.some.config.option", "some-value")
.master("local[*]")
.getOrCreate()

// 用于将DataFrames隐式转换成RDD,使df能够使用RDD中的方法。
import spark.implicits._

val df = spark.read.json("hdfs://datanode1:9000/input/sparksql/people.json")

// Displays the content of the DataFrame to stdout
df.show()

df.filter($"age" > 21).show()

df.createOrReplaceTempView("persons")

spark.sql("SELECT * FROM persons where age > 21").show()

spark.stop()
}
}

创建DataFrames

SparkSession是创建DataFrames和执行SQL的入口,创建DataFrames有三种方式,一种是可以从一个存在的RDD进行转换,还可以从Hive Table进行查询返回,或者通过Spark的数据源进行创建。

1
2
3
4
5
val df = spark.read.json("/input/sparksql/people.json")	
df.show()
val peopleRdd = sc.textFile("/input/sparksql/people.txt")
val peopleDF = peopleRdd.map(_.split(",")).map(paras => (paras(0),paras(1).trim().toInt)).toDF("name","age")
peopleDF.show()

常用操作

DSL风格语法

1
2
3
4
5
df.printSchema() 
df.select("name").show()
df.select($"name", $"age" + 1).show()
df.filter($"age" > 21).show()
df.groupBy("age").count().show()

SQL风格语法

1
2
3
4
5
6
df.createOrReplaceTempView("people")
val sqlDF = spark.sql("SELECT * FROM people")
sqlDF.show()
df.createGlobalTempView("people")
spark.sql("SELECT * FROM global_temp.people").show()
spark.newSession().sql("SELECT * FROM global_temp.people").show()

临时表是Session范围内的,Session退出后,表就失效了。如果想应用范围内有效,可以使用全局表。注意使用全局表时需要全路径访问,如:global_temp.people

创建DataSet

注意: Case classes in Scala 2.10只支持 22 字段. 你可以使用自定义的 classes 来实现对字段的映射
case class Person(name: String, age: Long)

1
2
3
4
5
6
7
8
9
10
case class Person(name: String, age: Long)
val caseClassDS = Seq(Person("Andy", 32)).toDS()
caseClassDS.show()
import spark.implicits._
val primitiveDS = Seq(1, 2, 3).toDS()
primitiveDS.map(_ + 1).collect()

val path = "/input/sparksql/people.json"
val peopleDS = spark.read.json(path).as[Person]
peopleDS.show()

相互转化

具体的转换可以参考: 三者共性

UDF函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.apache.spark.sql.SparkSession

object UDF {
def main(args: Array[String]): Unit = {
//创建SparkConf()并设置App名称
val spark = SparkSession.builder()
.appName("Spark SQL UDF example")
.master("local[*]")
.getOrCreate()
//读取数据
val df = spark.read.json("hdfs://datanode1:9000/input/sparksql/people.json")
df.show()

//注册UDF函数
spark.udf.register("AddOne", (age: Int) => age + 1)

df.createOrReplaceTempView("people")
//SQL语句
spark.sql("Select name,AddOne(age), age from people").show()

spark.stop()

}
}

自定义聚合函数

强类型的Dataset和弱类型的DataFrame都提供了相关的聚合函数, 如 count(),countDistinct(),avg(),max(),min()。除此之外,用户可以设定自己的自定义聚合函数。

弱类型用户自定义聚合函数:通过继承UserDefinedAggregateFunction来实现用户自定义聚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.hph.sql

import org.apache.spark.sql.{Row, SparkSession}
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._

//自定义UDAF函数需要继承UserDefinedAggregateFunction
class AverageSal extends UserDefinedAggregateFunction {
//输入数据
override def inputSchema: StructType = StructType(StructField("salary", LongType) :: Nil)

//定义每一个分区中的共享变量
override def bufferSchema: StructType = StructType(StructField("sum", LongType) :: StructField("count", IntegerType) :: Nil)

//表示UDAF函数的输出类型
override def dataType: DataType = DoubleType

//如果有相同的输入是否会存在相同的输出,如果是则为True
override def deterministic: Boolean = true

//初始化 每一个分区中的共享变量
override def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer(0) = 0L; // sum
buffer(1) = 0 // sum
}

//每一个分区中的每一条数据聚合的时候需要调用该方法
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
//获取这一行中的工资,然后将工资加入到sum里
buffer(0) = buffer.getLong(0) + input.getLong(0)
//需要将工资的个数加1
buffer(1) = buffer.getInt(1) + 1
}

//将每一个没去的输出合并形成最后的数据
override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
//合并总的工资
buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0)
//合并总的工资个数
buffer1(1) = buffer1.getInt(1) + buffer2.getInt(1)
}

//给出计算结果
override def evaluate(buffer: Row): Any = {
//取出总的工资 / 总的工资个数
buffer.getLong(0).toDouble / buffer.getInt(1)
}
}

object AverageSal {
def main(args: Array[String]): Unit = {

//创建SparkConf()并设置App名称
val spark = SparkSession.builder()
.appName("Spark SQL UDF example")
.master("local[*]")
.getOrCreate()

val employee = spark.read.json("hdfs://datanode1:9000/input/sparksql/employees.json")
employee.createOrReplaceTempView("employee")

spark.udf.register("average", new AverageSal)
spark.sql("select average(salary) from employee").show()
spark.stop()

}
}

强类型函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.hph.sql

import org.apache.spark.sql.{Encoder, Encoders, SparkSession}
import org.apache.spark.sql.expressions.Aggregator


case class Employee(name: String, salary: Long)

case class Aver(var sum: Long, var count: Int)

class Average extends Aggregator[Employee, Aver, Double] {
//初始化方法:初始化每一个分区的共享变量
override def zero: Aver = Aver(0L, 0)

//每一个分区的每一条数据聚合的时候需要回调该方法
override def reduce(b: Aver, a: Employee): Aver = {
b.sum = b.sum + a.salary
b.count = b.count + 1
b
}

//将每一个分区的输出 合并 形成最后的数据
override def merge(b1: Aver, b2: Aver): Aver = {
b1.sum = b1.sum + b2.sum
b1.count = b1.count + b2.count
b1
}

//输出计算结果
override def finish(reduction: Aver): Double = {
reduction.sum.toDouble / reduction.count
}

override def bufferEncoder: Encoder[Aver] = Encoders.product

override def outputEncoder: Encoder[Double] = Encoders.scalaDouble
}

object Average {
def main(args: Array[String]): Unit = {
//创建SparkConf()并设置App名称
val spark = SparkSession.builder()
.appName("Spark SQL Strong Type UDF example")
.master("local[*]")
.getOrCreate()
import spark.implicits._
val employee = spark.read.json("hdfs://datanode1:9000/input/sparksql/employees.json").as[Employee]
val aver = new Average().toColumn.name("average")
employee.select(aver).show()

spark.close()
}
}

上百节课详细讲解,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程介绍: 讲解一个真实的、复杂的大型企业级大数据项目,是Spark的大型项目实战课程。 通过本套课程的学习,可以积累大量Spark项目经验,迈入Spark高级开发行列。 课程特色: 1、项目中全面覆盖了Spark Core、Spark SQLSpark Streaming这三个技术框架几乎全部的初级和高级的技术点和知识点, 让学员学以致用,通过一套课程,即掌握如何将Spark所有的技术点和知识点应用在真实的项目中,来实现业务需求! 2、项目中的4个功能横块,全郃是实际企业项目中提取出来的,并进行技术整合和改良过的功能模块.全都是企业级的复杂和真实的需求,业务模块非常之复杂,绝对不是市面上的Dem级别的大数据项目能够想比拟的,学习过后,真正帮助学员增加实际 企业级项目的实战经验。 3、项目中通过实际的功能模块和业务场景,以及讲师曾经开发过的处理十亿、甚至百亿以上数据级别的SparK作业的经验积累,贯穿讲解了大量的高级复杂的性能调优技术和知识、troubleshooting解决线上报错和故障的经验、高端的全方位数据倾斜处理和解决方案.真正帮助学员掌握高精尖的Spark技术! 4、项目中采用完全还原企业大数据项目开发场景的方式来讲解,每一个业务模块的讲解都包括了需求分析、方案设计、数据设计、编码实现、功能测试、性能调优等环节,真实还原企业级大数据项目开发场景。 模块简介: 1、用户访问session分析,该模块主要是对用户访问session进行统计分析.包括session的聚合指标计算、 按时间比例随机抽取session、获取每天点击、下单和购买排名前10的品类、并获取top10品类的点击量排名前10的session.该模块可以让产品经理、数据分析师以及企业管理层形象地看到各种条件下的具体用户行为以及统计指标.从而对公司的产品设计以及业务发展战略做出调整.主要使用Spark Core实现. 2、页面单跳转化率统计,该模块主要是计算关键页面之间的单步跳转转化率,涉及到页面切片算法以及页面流匹配算法.该模块可以让产品经理、数据分析师以及企业管理层看到各个关键页面之间的转化率.从而对网页布局,进行更好的优化设计。主要使用Spark Core实现. 3、热门商品离线统计,该模块主要实现每天统计出各个区域的top3热门商品.然后使用Oozie进行离线统计任务的定时调度,使用Zeppeline进行数据可视化的报表展示.该模块可以让企业管理层看到公司售卖的 商品的整体情况,从而对公司的商品相关的战略进行调螫.主要使用Spark SQL实现。 4、广告流量实时统计.该模块负责实时统计公司的广告流量.包括广告展现流量和广告点击流量,实现动态黑名单机制以及黑名单过滤,实现滑动窗口内的各城市的广告展现流立和广告点击流直的统计,实现 每个区域诲个广告的点击流置实时统计,实现每个区域top3点击量的广告的统计,主要使用Spark Streaming实现.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值