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")//指定保存路径和输出目录
  }
}
posted @ 2022-03-12 14:13  阿伟宝座  阅读(398)  评论(0)    收藏  举报