Spark知识点整理(二)——SparkSQL部分

1.SparkSQL概述

  • (1) 定义:SparkSQL是基于SparkCore专门为模块化计算设计的模块
  • (2) 功能:
    提供SQL和DSL开发接口,将SQL或者DSL语句转换为SparkCore程序,实现结构化的数据处理
  • (3) 特点
    • Integrated:集成了大多数的开发接口
      • DSL:函数式编程实现开发,可使用DSL函数、RDD函数以及SQL关键字形成的函数
      • SQL:使用SQL语句编程开发
    • Uniform Data Access:统一化的数据访问
      封装了常用的所有数据源读写接口,文件(csv/tsv/parquet/orc/json)和数据库(MySQL、Hive)
    • Hive Integration:Hive的集成
      兼容Hive的开发方式,可直接访问Hive数仓
    • Standard Connectivity:标准的数据连接接口
      SQL、JAR、JDBC、beeline等
  • (4) 应用场景
    • ① 离线:代替SparkCore:SQL + DSL,访问Hive数据仓库中的数据进行处理
    • ② 实时:StructStreaming(结构化流计算)

2.SparkSQL代码开发模板

import org.apache.spark.sql.SparkSession

/**
 * @Todo:  SparkSQL代码模板
 * @auther: Cjp
 * @date: 2021/7/15 20:29
 */

object saprkSqlMode {
  def main(args: Array[String]): Unit = {
    //todo:1-构建驱动对象:sparksession
    val spark:SparkSession = SparkSession
      .builder()//构建一个建造器
      .master("local[2]")//配置运行模式
      .appName(this.getClass.getSimpleName.stripSuffix("$"))//设置程序名称
//      .config("key","value")//配置其他属性(内存,核数)
      .getOrCreate()//返回一个sparksession对象

    //更改日志级别
    spark.sparkContext.setLogLevel("WARN")

    //todo:2-实现处理的逻辑
    //step1:读取数据
    //step2:转换数据
    //step3:保存结果

    //todo:3-释放资源
    spark.stop()
  }
}
  • (1) sparkDSL:函数式编程
    • ① 提供了SQL的关键字函数、兼容RDD的转换函数
    • ② 与RDD区别:调用函数不一样
      • DSL函数 :SQL关键字函数:select、where、groupBy、orderBy、limit、agg
      • RDD函数 :结构化数据处理的函数:map、flatMap、filter
  • (2) sparkSQL:基于SQL进行处理,开发流程如下:
    • ① 将DF或者DS注册为一个只读表:视图
    • ② 通过SQL对视图进行处理,返回一个新的DF或者DS

3.SparkCore与SparkSQL是设计对比

  • (1) SparkCore的设计

    • ① 设计:
      将所有数据放入分布式数据集合,调用集合的转换函数来实现处理,返回新的结果集合
    • ② 实现:
      • 数据抽象:RDD【分布式集合:数据】
      • 数据驱动:SparkContext
    • ③ 应用场景
      使用函数式编程对各种数据源的数据进行分布式的计算处理
    • ④ 瓶颈
      RDD中只有数据,没有数据的Schema,SparkCore处理结构化数据不如SQL更方便直观
  • (2) SparkSQL的设计

    • ① 设计:
      将所有数据放入分布式数据表中,使用SQL或者DSL函数来实现处理,返回新的数据表
    • ② 实现
      • 数据抽象:DataSet / DataFrame 【分布式表:数据 + Schema】
      • 数据驱动:SparkSession
    • ③ 应用场景
      使用SQL或者DSL对结构化数据源的数据进行分布式的计算处理
  • (3) 数据抽象之间的区别与联系

    • ① 数据抽象设计概述

      • RDD:SparkCore中的分布式集合,用于存储数据
      • DataFrame(简称DF):早期的SparkSQL中分布式表的设计(1.3版本参考Python的数据结构实现)
      • DataSet(简称DS):后期SparkSQL中分布式表的设计
        • 1.6版本开始引用(参考Flink设计),保留了DataFrame
        • 2.0版本开始,将DF作为DS的一种特殊形式,只保留了DataSet数据结构
    • ② 关系与区别
      在这里插入图片描述

      • RDD:RDD【T】:数据 + 支持泛型
      • DataFrame:DataFrame:数据 + Schema
        • 没有泛型,固定为Row类型
        • DataFrame = DataSet[Row]
      • DataSet:DataSet【T】 :数据 + Schema + 泛型
    • ③ 关系转换
      在这里插入图片描述

      • DF/DS转RDD(使用函数)
        • .rdd:从DS或者DF取出RDD
        • .schema:从DS或者DF取出Schema
      • RDD转DF/DS
        • 方式一:反射类型推断
        • 方式二:自定义Schema
  • (4) RDD转DF/DS实现

    • ① 反射类型推断
      • 功能 :将RDD中的泛型进行修改,将没有Schema类型,更改为有Schema类型,将每条数据从String类型变成一个JavaBean(样例类)
      • 使用场景 :适合于Schema比较固定的场景
    • ② 自定义Schema
      • 功能 :自定义Schema,与RDD合并构建DataFrame
      • 使用场景 :适合于字段不固定的场景

4.SparkDSL与SparkSQL是设计对比

  • (1) DSL开发

    • ① 利用函数式编程的方式来开发SparkSQL程序,类似于SparkCore方式
    • ② 流程
      • step1:读取数据放入DF或者DS
      • step2:调用函数来对DF或者DS进行转换
        • RDD的转换函数:map、flatMap、filter……
        • SparkSQL中的DSL函数:select、where、groupBy、limit、orderBy
      • step3:保存计算以后的结果
  • (2) SQL开发

    • ① 利用SQL方式来开发SparkSQL程序,类似于Hive中的使用方式
    • ② 流程
      • step1:读取数据放入DF或者DS
      • step2:将DF或者DS注册为视图,调用SQL语句来实现处理
      • step3:保存计算以后的结果
  • (3) 性能

    • ① DSL与SQL在性能上没有差异
    • ② SparkSQL的底层还是SparkCore,所有计算最终还是由RDD的转换函数来实现
    • ③ DS或者DF继承了RDD的特性
      • 所有转换都是Lazy模式
      • DS或者DF也继承了RDD的五大特性
      • 也拥有persist和checkpoint

5.Spark的数据源Source、Sink和SaveMode模式

  • (1) SparkSQL有哪些常用的数据源source接口
    • ① Parquet文件(SparkSQL默认读取的文本类型就是Parquet)
    • ② JSON文件
    • ③ CSV文件(以逗号分隔的文件)
    • ④ MySQL数据(jdbc文件)
    • ⑤ 调用代码格式:spark.read.format(“格式”).load(“路径”)
spark.read.csv/partquet/orc/json/jdbc/table

举例:

spark.read.format("json").load("datas/people.json")
//等同于
spark.read.json("datas/people.json")
  • (2) SparkSQL的数据源Sink
    • ① 可保存的格式:与数据源接口文件一致
    • ② 语法:
df/ds.write.mode
	.format
	.save/save(Path)/saveAsTable
  • save(Path:String):用于保存文本
  • save():用于保存数据库
  • saveAsTable:保存到Hive表中
//保存方式一:redis、hbase、JDBC
df/ds.foreachPartition(自定义保存的逻辑)

//保存方式二
df/ds.write.mode.jdbc => df/ds.write.mode.format("输出的格式").save("路径")

//保存方式三
df/ds
  .write
  .mode(SaveMode.Overwrite)
  .format("指定保存格式")
  .save("保存的路径")/save()/saveAsTable

  • (3) SaveMode:保存模式的几种方式

    • ① Append:追加模式
    • ② ErrorIfExists:如果数据结果已存在就抛出异常
    • ③ OverWrite:覆盖模式
    • ④ Ignore:如果数据已存在,就忽略
  • (4) 保存为jdbc格式文件时(即写入数据库,如mysql,oracl)存在的问题:
    主键 + 约束的格式导致 如果用追加:主键重复,如果用覆盖,数据丢失
    解决方式:

    • 如果用官方的JDBC:1-建MySQL表时,允许主键自动更新 2-使用追加模式
    • 如果不用官方的JDBC:自己写
ds.foreachPartition (part => {
	//JDBC
	//replace into 
})

6.Shuffle分区数

  • (1) 现象:SparkSQL程序不论数据量的多少,在经过聚合shuffle时,RDD分区数会变为200
    在这里插入图片描述

  • (2) 原因:SparkSQL设计时聚合shuffle的分区数默认为200
    在这里插入图片描述

  • (3) 弊端:某些情况比如数据量不大时不需要用到200个分区,空间浪费

  • (4) 解决方式:根据数据量调整分区个数

spark.builder			
	.config("spark.sql.shuffle.partitions","2") 
	//调整Shuffle分区个数为2

7.SparkSQL的hive集成开发

  • (1) 设计:所有需要访问Hive数据仓库的分布式计算服务,只要知道metastore服务的地址,就可以访问Hive元数据了
    在这里插入图片描述

  • (2) 开发

    • ① DSL
      • step1:加载Hive表的数据变成DataSet或者DataFrame:spark.read.table
      • step2:使用DSL进行处理
    • ② SQL:spark.sql直接使用SQL进行处理
  • (3) 应用场景

    • ① SparkSQL/Impala:分布式内存计算框架:SQL
    • ② 代替Hive进行计算:Hive主要作用构建数据仓库
    • ③ SQL
      • DDL:HiveSQL + MetaStore
      • DML:SparkSQL 、Impala
      • DQL:SparkSQL 、Impala

8.SparkSQL中自定义UDF

规则:

  • (1) SQL:
spark.register.udf(函数名,函数体)
  • (2) DSL:
val 函数名 = udf(函数体)

9.SparkSQL的常用开发方式小结

  • (1)场景一:代码测试
    • ①方式一:IDEA中开发/Spark Shell,直接做本地代码运行测试
    • ②方式二:SparkSQL Shell,类似于Hive Shell,直接写SQL
    • ③方式三:Beeline,通用JDBC命令行
  • (2)场景二:生产运行
    • ①方式一:jar包运行,将IDEA中开发的SparkSQL代码打成jar包,通过spark-submit提交运行
    • ②方式二:SQL 脚本,将SQL语句封装在SQL脚本中,执行SQL脚本,spark-sql -f xxxx.sql
    • ③方式三:JDBC,应用型的SparkSQL的数据处理
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值