SparkSQL

一、RDD、DataFrame和DataSet

1,共性

1、RDD、DataFrame和DateSet全都是spark平台下的弹性分布式数据集
2、三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action如foreach时,三者才会开始遍历
3、三者都有partition的概念,有共同的函数如filter、排序等
4、在对DataFrame和DataSet进行许多操作都需要进行支持import spark.implicits._

2,区别

1、RDD不支持sparksql,而DataFrame和DataSet则支持sparkSql可创建临时表/视图
2、DataFrame和DataSet拥有完全相同的成员函数,区别只是每一行的数据类型不同。DataFrame也可以认为是Dataset[Row]

 

二、自定义函数

1,用户自定义UDF

spark.udf.register("addName", (x:String)=> "Name:"+x) //spark(sparksession)
spark.sql("Select addName(name), age from people").show()

2,用户自定义UDAF

  a)弱类型

**
  * 自定义聚合函数
  */
class MyUDAF 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
    buffer(1) = 0L
  }
  //更新
  override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
    buffer(0) = buffer.getLong(0) + input.getLong(0) //input对应输入值
    buffer(1) = buffer.getLong(1) + 1
  }
  //不同的execute间的数据合并
  override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
    buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0)
    buffer1(1) = buffer1.getLong(1) + buffer2.getLong(1)
  }
  //计算最终输出
  override def evaluate(buffer: Row): Any = {
    buffer.getLong(0).toDouble / buffer.getLong(1)
  }
}
//自定义聚合函数的使用
val udaf = new MyUDAF spark.udf.register("ageAvg",udaf) //注册自定义聚合函数 spark.sql("select avg(age) from user").show()

  b)强类型

case class User(name:String,age:Long)
case class Average(var sum:Long,var count :Long)

/**
  * -IN, BUF, OUT
  * 输入为User   缓存为Average   输出为Double平均值
  */
object MyAVG extends Aggregator[User,Average,Double] {
  //初始化
  override def zero: Average = Average(0L,0L)
  //化简
  override def reduce(b: Average, a: User): Average = {
    b.sum += a.age
    b.count += 1
    b
  }
  //Executor之间合并
  override def merge(b1: Average, b2: Average): Average = {
    b1.sum += b2.sum
    b1.count += b2.count
    b1
  }
  //最终输出
  override def finish(reduction: Average): Double = reduction.sum.toDouble / reduction.count

  override def bufferEncoder: Encoder[Average] = Encoders.product //自定义数据类型

  override def outputEncoder: Encoder[Double] = Encoders.scalaDouble //基本数据类型
}
//使用案例
val myavg = MyAVG.toColumn.name("myavg")
import spark.implicits._
df.as[User].select(myavg).show(

 

三、Spark的数据源

文件保存选项SaveMode

 

SaveMode.Append          //追加
SaveMode.Overwrite       //覆写
SaveMode.ErrorIfExists   //默认,如果存在报错
SaveMode.Ignore          //数据存在,则忽略

 

1,json、parquet

//通用方式
spark.read.format("json").load("path")
spark.read.format("parquet").load("path")
//json方式
spark.read.json("path")
//parquet
df.write.parquet("path")

2,JDBC

 

//读取方式一
val jdbcDF = spark.read
    .format("jdbc")
    .option("url", "jdbc:mysql://linux1:3306/rdd")
    .option("dbtable", "tableName")
    .option("user", "root")
    .option("password", "000000")
    .load()
//读取方式二
val connectionProperties = new Properties()
connectionProperties.put("user", "root")
connectionProperties.put("password", "000000")
val jdbcDF2 =spark.read.jdbc("jdbc:mysql://linux1:3306/rdd","tableName", connectionProperties)
//写入方式一
jdbcDF.write
    .format("jdbc")
    .option("url", "jdbc:mysql://linux1:3306/rdd")
    .option("dbtable", "tableName")
    .option("user", "root")
    .option("password", "000000")
    .save()
//写入方式二
jdbcDF2.write.jdbc("jdbc:mysql://linux1:3306/rdd", "db", connectionProperties)

 

3,Hive

  如果是引用外部的hive,只需要将hive-site.xml,拷贝至Spark的conf目录下(spark与hive交互)或是拷贝至resource目录下。

 

posted @ 2020-07-23 09:05  MXC肖某某  阅读(192)  评论(0编辑  收藏  举报