Spark SQL的介绍和WordCount案例
Spark SQL的介绍和WordCount案例
Hive SQL是在Hive命令行里编写
DataSource API
数据源API
Spark SQL可以读取很多格式的数据,常用的有以下三种:
1、CSV----文本格式
2、JSON
3、JDBC----数据库的格式
DataFrame API
数据框API
1、DSL----类SQL语法(介于代码和SQL之间的写法)
2、Spark SQL、HQL
Spark中是可以用Hive SQL(HQL)的,Spark SQL和Hive SQL是完全兼容的
DSL----类SQL语法
类SQL语法--介于代码和SQL之间的写法
DSL比代码简单,比SQL好用,工作开发中普遍使用
DataFrame与RDD的比较
DataFrame与RDD类似,也是一个分布式数据容器。
DataFrame相当于数据库的二维表格,除了数据以外,还掌握数据的结构信息,即schema。
同时,与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)。
从API易用性的角度上看,DataFrame API提供的是 一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低。
由于与R和Pandas的 DataFrame类似,Spark DataFrame很好地继承了传统单机数据分析的开发体验。
DataFrame:数据框,相当于一张表,包含列名;
底层也是RDD,在RDD的基础上增加了列名;
增加了列名,就可以写SQL
Spark SQL应用
1、Spark SQL属于代码+SQL一起编写
2、当使用Spark SQL的时候,环境和入口和Spark之前的不一样的
3、SparkSQL需要我们设置分区数(默认是200个分区)
不设置的话, 在shuffle之后默认200个分区,执行代码太慢,
而且在保存数据的时候,还会生成很多个给文件
//创建SparkSession环境 val spark: SparkSession = SparkSession .builder() .appName("sql") .master("local") .config("spark.sql.shuffle.partitions",1) //设置SparkSQL shuffle之后的分区数(不设置的话,默认是200个分区,执行代码太慢了) .getOrCreate() //读取文件构建DF val linesDF: DataFrame = spark .read .format("csv")//指定读取文件的格式 .option("sep","*") //指定分割方式和分隔符(CSV默认分隔符是逗号,使用*分割,数据就变成了一列) .schema("line STRING") //指定字段名和字段类型,用空格分开(当字段只有一个,用line) .load("data/words.txt")//指定读取文件的路径,用来加载
编写代码之前需要导入spark sql的依赖
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.4.5</version>
</dependency>
Spark SQL----WordCount示例
package com.shujia.sql
import org.apache.spark.sql.{DataFrame, SparkSession}
object Demo1WordCount {
def main(args: Array[String]): Unit = {
/**
* 创建SparkSession环境
*/
val spark: SparkSession = SparkSession
.builder()
.appName("sql")
.master("local")
.getOrCreate()
//读取文件构建DF
val linesDF: DataFrame = spark
.read
.format("csv")//指定读取文件的格式
.option("sep","*")//指定分割方式和分隔符(CSV默认分隔符是逗号,使用*分割,数据就变成了一列)
.schema("line STRING")//指定字段名和字段类型,用空格分开(当字段只有一个,用line)
.load("data/words.txt")//指定读取文件的路径,用来加载
// linesDF.show()
/**
* 通过写SQL,统计单词数量
* 如果写SQL,需要先注册一张表
*/
//将DF注册成一张表(临时视图)
linesDF.createOrReplaceTempView("lines")
//编写SQL
//spark.sql("SQL语句") 这样写SQL代码会很难看,使用下面这种:括号内打出3个双引号回车
val countDF: DataFrame = spark.sql(
"""
|select
|word,count(1) as wordNum
|from(
|select
|explode(split(line,',')) as word
|from
|lines) as t
|group by word
|""".stripMargin)
countDF.show()
}
}
执行结果
+------+-------+
| word|wordNum|
+------+-------+
| spark| 12|
| java| 12|
|hadoop| 6|
| hive| 6|
+------+-------+
DSL----WordCount示例
DSL---类SQL(介于代码和SQL之间的语法)
1、DSL不需创表
2、在Spark中使用DSL需要导包
3、在DSL中不需要子查询嵌套
4、DSL中使用字段名需要加$
5、DSL执行顺序:从上往下
SQL执行顺序:从内往外
6、DSL分组---groupBy
SQL分组---group by
package com.shujia.sql
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}
object Demo1WordCount {
def main(args: Array[String]): Unit = {
/**
* 创建SparkSession环境
*/
val spark: SparkSession = SparkSession
.builder()
.appName("sql")
.master("local")
.getOrCreate()
//读取文件构建DF
val linesDF: DataFrame = spark
.read
.format("csv")//指定读取文件的格式
.option("sep","*")
//指定分割方式和分隔符(CSV默认分隔符是逗号,使用*分割,数据就变成了一列)
.schema("line STRING")//指定字段名和字段类型,用空格分开(当字段只有一个,用line)
.load("data/words.txt")//指定读取文件的路径,用来加载
/**
* DSL---类SQL(介于代码和SQL之间的语法)
* 1、DSL不需创表
* 2、在Spark中使用DSL需要导包
* 3、在DSL中不需要子查询嵌套
* 4、DSL中使用字段名需要加$
* 5、DSL执行顺序:从上往下
* SQL执行顺序:从内往外
* 6、DSL分组---groupBy
* SQL分组---group by
*/
//导包--导入sql所有的函数
import org.apache.spark.sql.functions._
//导入隐式转换
import spark.implicits._
val dslCount: DataFrame = linesDF
.select(explode(split($"line",",")) as "word")
.groupBy($"word")
.count()
dslCount.show()
}
}
执行结果
+------+-------+
| word| count|
+------+-------+
| spark| 12|
| java| 12|
|hadoop| 6|
| hive| 6|
+------+-------+
保存DF数据
dslCount .write //保存数据 .format("json") //指定保存数据的格式 .mode(SaveMode.Overwrite) //指定保存模式(Overwrite覆盖,Append追加,ErrorIfExists存在会报错) .save("data/sql_count") //指定保存路径和输出目录
package com.shujia.sql
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}
object Demo1WordCount {
def main(args: Array[String]): Unit = {
/**
* 创建SparkSession环境
*/
val spark: SparkSession = SparkSession
.builder()
.appName("sql")
.master("local")
.getOrCreate()
//读取文件构建DF
val linesDF: DataFrame = spark
.read
.format("csv")//指定读取文件的格式
.option("sep","*")
//指定分割方式和分隔符(CSV默认分隔符是逗号,使用*分割,数据就变成了一列)
.schema("line STRING")//指定字段名和字段类型,用空格分开(当字段只有一个,用line)
.load("data/words.txt")//指定读取文件的路径,用来加载
// linesDF.show()
/**
* 通过写SQL,统计单词数量
* 如果写SQL,需要先注册一张表
*/
//将DF注册成一张表(临时视图)
linesDF.createOrReplaceTempView("lines")
//编写SQL
//spark.sql("SQL语句") 这样写SQL代码会很难看,使用下面这种:括号内打出3个双引号回车
val countDF: DataFrame = spark.sql(
"""
|select
|word,count(1) as wordNum
|from(
|select
|explode(split(line,',')) as word
|from
|lines) as t
|group by word
|""".stripMargin)
// countDF.show()
/**
* DSL---类SQL(介于代码和SQL之间的语法)
* 1、在Spark中使用DSL需要导包
* 2、在DSL中不需要子查询嵌套
* 3、DSL中使用字段名需要加$
* 4、DSL执行顺序:从上往下
* SQL执行顺序:从内往外
*/
//导包--导入sql所有的函数
import org.apache.spark.sql.functions._
//导入隐式转换
import spark.implicits._
val dslCount: DataFrame = linesDF
.select(explode(split($"line",",")) as "word")
.groupBy($"word")
.count()
dslCount.show()
/**
* 保存数据
*/
dslCount
.write//保存数据
.format("json")//指定保存数据的格式
.mode(SaveMode.Overwrite)
//指定保存模式(Overwrite覆盖,Append追加,ErrorIfExists存在会报错)
.save("data/sql_count")//指定保存路径和输出目录
}
}

浙公网安备 33010602011771号