• SparkSQL


    数据源

    SparkSQL默认数据源为Parquet格式(面向列存储)。
    将其他格式转换为Parquet后再读取

    spark.read.format("json").load(path)
    

    同样如果是保存,要将格式先进行转换,否则保存下来的数据为Parquet格式
    df.write.format("json").mode("append").save(path)

    1.从MySQL读取

    val jdbcDF = spark.read.format("jdbc").option("url","jdbc:mysql://.....").option("dbtable",""tablename").ption("user","root").option("password","xxxx").load()  
    

    2.写入MySQL

    jdbcDF.write.format("jdbc").option("url","jdbc:mysql://.....").option("dbtable",""tablename").ption("user","root").option("password","xxxx").save()  
    

    DataFrame

    与RDD类似,DataFrame是一个分布式数据容器,更像传统数据库的二维表格,除了记录数据意以外,还记录数据的结构信息,即schema。同时,与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)。从API易用性的角度上看,DataFrame API提供的是一套高层的关系操作,比函数式RDD API 更加友好,门槛更低。

    1.创建方式

    • 通过spark的数据源进行创建
    spark.read.文件格式
    
    • 从一个存在的RDD进行转换
      - 手动确定转换RDD.toFD(字段名称)
      - 通过反射确定(需要用到样例类)
      - 通过编程方式

    • 还可以从Hive Table进行查询返回

    DataSet

    是DataFrame API的一个扩展,是Spark最新的数据抽象,既具有类型安全检查也具有DataFrame的查询优化特性。支持编码器,当需要访问非堆上的数据时,可以避免反序列化整个对象,提高效率。DataFrame是DataSet的特例,DataFrame=DataSet[class]
    1.创建方式

    • RDD.toDS

    需要用到样例类

    • DF.as(类型)

    在RDD与DF或者DS之间操作时,要引入隐式转换 import spark.implicits._
    这里的spark不是包名,而是SparkSession对象

    UDF自定义函数

    spark.udf.register("methodname",(function))
    

    一、自定义聚合函数(弱类型)

    #1.声明自定义聚合函数
    class MyFunction extends UserDefinedAggregateFunction{
          #函数输入的数据结构
          override def inputSchema:StructType = {
                new StructType().add("age",LongType)
          }
          #计算时的数据结构
          override def bufferSchema:StructType={
                new StructType().add("sum",LongType).add("count",LongType)
          }
          #函数返回的数据类型
          override def dataType:DataType= DoubleType
          #函数是否稳定
          override def deterministic:Boolean = true
          #计算之前的缓冲区的初始化
          override def initialize(buffer: MutableAggregationBuffer): Unit = {
                buffer(0)=0L #代表 bufferschema中第一个数据结构的初始化值
                buffer(1)=1L
          }
          #将多个节点的缓冲区合并
          override def merge(buffer1:MutableAggregationBuffer,buffer2:Row):Unit={
                //sum
                buffer1(0)=buffer1.getLong(0) + buffer2.getLong(0)
                //count
                buffer1(1)=buffer1.getLong(1) + buffer2.getLong(1)
           }
           #根据查询结果更新缓冲区的数据
          override def update(buffer:MutableAggregationBuffer, input:Row):Unit={
                 buffer(0)= buffer.getLong(0) +input.getLong(0)
                 buffer(1)= buffer.getLong(0) + 1
          }
          #计算
          override def evaluate(buffer:Row):Any={
                buffer.getLong(0).toDouble/buffer.getLong(1)
          }
    }
    #2.使用聚合函数
          val udaf = new MyFunction()
          spark.udf.register("xxx",udaf)
    

    二、自定义聚合函数(强类型)

    object UDFA_class {
      def main(args: Array[String]): Unit = {
    
        val conf = new SparkConf().setMaster("local[*]").setAppName("ooo")
        val spark: SparkSession = SparkSession.builder().config(conf).getOrCreate()
    
        import spark.implicits._
    
        val udaf = new MyFunction()
    
        //将聚合函数转换为查询列
        val avgCol: TypedColumn[UserBean, Double] = udaf.toColumn.name("avgAge")
    
        val frame = spark.read.json("in/user.json")
        val userDS: Dataset[UserBean] = frame.as[UserBean]
    
        userDS.select(avgCol).show()
    
        spark.close()
      }
    
      case class UserBean (name : String, age : BigInt)
      case class AvgBuffer(var sum:BigInt,var count:Int)
    
      class MyFunction extends Aggregator[UserBean,AvgBuffer,Double]{
        //缓冲区初始化
        override def zero: AvgBuffer = {
          AvgBuffer(0,0)
        }
    
        //聚合数据
        override def reduce(b: AvgBuffer, a: UserBean): AvgBuffer = {
          b.sum = b.sum+a.age
          b.count=b.count+1
          b
        }
    
        //两个节点缓冲区合并
        override def merge(b1: AvgBuffer, b2: AvgBuffer): AvgBuffer = {
          b1.sum=b1.sum+b2.sum
          b1.count=b1.count+b2.count
          b1
        }
    
        //完成计算
        override def finish(reduction: AvgBuffer): Double = {
          reduction.sum.toDouble/reduction.count
        }
    
        //如果是自己定义的类,就是Encoders.product,否则Encoders.scalaDouble
        override def bufferEncoder: Encoder[AvgBuffer] = Encoders.product
    
        override def outputEncoder: Encoder[Double] = Encoders.scalaDouble
      }
    
    }
    
  • 相关阅读:
    Spring Boot 使用 Dev-tool 热部署
    Spring Boot 上传文件
    Spring Boot 目录文件结构
    Spring MVC 文件上传
    Spring MVC 混合使用多种视图技术
    XmlViewResolver 和 ResourceBundleViewResolver
    XML 和 Json
    Excel 和 PDF
    04-树5 Root of AVL Tree (25 分)
    04-树4 是否同一棵二叉搜索树 (25 分)
  • 原文地址:https://www.cnblogs.com/zqzhen/p/12861018.html
Copyright © 2020-2023  润新知