Scala | SparkSQL | 创建DataSet | 序列化问题 | UDF与UDAF | 开窗函数

本文详细介绍了SparkSQL的起源、概念和数据源,探讨了如何创建Dataset,特别是从JSON、RDD、Parquet、JDBC和Hive中创建。接着,讨论了序列化问题,包括版本不一致和对象的序列化机制。此外,还深入讲解了自定义函数UDF和UDAF的实现。最后,阐述了开窗函数在数据处理中的应用。
摘要由CSDN通过智能技术生成



一、SparkSQL

1.SparkSQL介绍

  HiveShark 的前身,SharkSparkSQL 的前身,SparkSQL 产生的根本原因是其完全脱离了 Hive 的限制

  • SparkSQL 支持查询原生的 RDDRDDSpark 平台的核心概念, 是 Spark 能够高效的处理大数据的各种场景的基础。
  • 能够在 scalaJava中写 SQL 语句。支持简单的 SQL 语法检查,能够在Scala 中写 Hive 语句访问 Hive 数据,并将结果取回作为 RDD 使用。
  • Spark on HiveHive 只作为储存角色,Spark 负责 sql 解析优化,执行。
  • Hive on SparkHive 即作为存储又负责 sql 的解析优化,Spark 负责执行。

两者数据源均为Hive表,底层人物均为Spark人物,关键区别在于一个是Hive去解析,一个是Spark去解析。

name 存数据的位置 解析引擎 执行引擎
hive on spark hive表 hive spark
spark on hive hive表 spark spark

2.Dataset 与 DataFrame概念解析

在这里插入图片描述

  Dataset 也是一个分布式数据容器。与 RDD 类似,然而 Dataset 更像传统数据库的二维表格,除了数据以外,还掌握数据的结构信息(元数据),即schema。同时,与 Hive 类似,Dataset 也支持嵌套数据类型(struct、array 和 map)。从 API 易用性的角度上 看, Dataset API 提供的是一套高层的关系操作,比函数式的 RDD API 要更加友好,门槛更低。Dataset 的底层封装的是 RDD,当 RDD 的泛型是 Row 类型的时候,我们也可以称它为 DataFrame

Dataset<Row> = DataFrame

3.SparkSQL 的数据源

  SparkSQL 的数据源可以是 JSON 类型的字符串,JDBCParquentHiveHDFS 等。
在这里插入图片描述
可以将不同源中的数据进行join,这就是SparkSQL中的异构数据源的操作。

4.SparkSQL 底层架构

  首先拿到 sql 后解析一批未被解决的逻辑计划,再经过分析得到分析后的逻辑计划,再经过一批优化规则转换成一批最佳优化的逻辑计划,再经过 SparkPlanner 的策略转化成一批物理计划,随后经过消费模型转换成一个个的 Spark 任务执行。
在这里插入图片描述

5.谓词下推(predicate Pushdown)

在这里插入图片描述

二、创建DataSet的几种方式

1.读取 json 格式的文件创建 Dataset

  读取 json 格式的文件有两种方式:

  • 一种是spark.read.json(文件路径)
  • 另一种是spark.read.format("json").load(文件路径)

注意

  • json 文件中的 json 数据不能嵌套 json 格式数据。
  • Dataset 是一个一个 Row 类型的 RDDds.rdd()/ds.javaRdd()
  • df.show()默认显示前 20 行数据。
  • json文件自带元数据,默认排序时字段名按照字典序排序,然后类型自动推断。
  • 注册成临时表时,表中的列默认按 ascii 顺序显示列。
package com.shsxt.scala_Test.sql.dataset

import org.apache.spark.sql.{
   DataFrame, SQLContext, SparkSession}

object CreateDFFromJsonFile {
   
  def main(args: Array[String]): Unit = {
   
    val spark: SparkSession = SparkSession
      .builder()
      .master("local")
      .appName("jsonRDD")
      .getOrCreate()


    val jsonDS: DataFrame = spark.read.json("./data/json")

    jsonDS.show();

    jsonDS.createOrReplaceTempView("jsonTable")

    val result: DataFrame = spark.sql("select * from jsonTable where age is not NULL")
    result.show()
    spark.stop()
  }
}
+----+--------+
| age|    name|
+----+--------+
|  18|zhangsan|
|null|    lisi|
|  18|  wangwu|
|  28|  laoliu|
|  20|zhangsan|
|null|    lisi|
|  18|  wangwu|
|  28|  laoliu|
|  28|zhangsan|
|null|    lisi|
|  18|  wangwu|
+----+--------+

+---+--------+
|age|    name|
+---+--------+
| 18|zhangsan|
| 18|  wangwu|
| 28|  laoliu|
| 20|zhangsan|
| 18|  wangwu|
| 28|  laoliu|
| 28|zhangsan|
| 18|  wangwu|
+---+--------+

2.通过 json 格式的 RDD 创建 Dataset

package com.shsxt.scala_Test.sql.dataset

import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{
   DataFrame, Dataset, SQLContext, SparkSession}


case class Person(id: String, name: String, age: Integer)


object CreateDFFromRDDWithReflect {
   
  def main(args: Array[String]): Unit = {
   
    val spark: SparkSession = SparkSession
      .builder()
      .master("local")
      .appName("jsonRDD")
      .getOrCreate()

    val sc: SparkContext = spark.sparkContext
    val nameRDD: RDD[String] = sc.parallelize(Array(
      "{'name':'zhangsan','age':\"18\"}",
      "{\"name\":\"lisi\",\"age\":\"19\"}",
      "{\"name\":\"wangwu\",\"age\":\"20\"}"))

    val scoreRDD: RDD[String] = sc.parallelize(Array(
      "{\"name\":\"zhangsan\",\"score\":\"100\"}",
      "{\"name\":\"lisi\",\"score\":\"200\"}",
      "{\"name\":\"wangwu\",\"score\":\"300\"}"
    ))

    val name: DataFrame = spark.read.json(nameRDD)
    val score: DataFrame = spark.read.json(scoreRDD)

    //注册成临时表使用
    name.createOrReplaceTempView("nameTable");
    score.createOrReplaceTempView("scoreTable");
    val result: DataFrame = spark.sql(
      """
        |select nameTable.name,nameTable.age,scoreTable.score
        |from nameTable join scoreTable
        |on nameTable.name = scoreTable.name
        |""".stripMargin)
    result.show()

    spark.stop()
  }
}
+--------+---+-----+
|    name|age|score|
+--------+---+-----+
|  wangwu| 20|  300|
|zhangsan| 18|  100|
|    lisi| 19|  200|
+--------+
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幼稚的人呐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值