SparkSQL中UDF和UDAF

9 篇文章 0 订阅
UDF: User Defined Function,用户自定义的函数,函数的输入是一条具体的数据记录,实现上讲就是普通的Scala函数;

UDAF:User Defined Aggregation Function,用户自定义的聚合函数,函数本身作用于数据集合,能够在聚合操作的基础上进行自定义操作,更具体一点就是,UDAF要和SQL语句中的 group by(分组操作)联合使用,UDAF操作的元素就是分组时,组中的每个数据进行聚合得出结果,然后在进行下一个组的聚合

实质上讲,例如说UDF会被Spark SQL中的Catalyst封装成为Expression,最终会通过eval方法来计算输入的数据Row(此处的Row和DataFrame中的Row没有任何关系)


不说太多直接上代码


1、创建Spark的配置对象SparkConf,设置Spark程序的运行时的配置信息

[java]  view plain  copy
  1. val conf = new SparkConf() //创建SparkConf对象  
  2. conf.setAppName("SparkSQLUDFUDAF"//设置应用程序的名称,在程序运行的监控界面可以看到名称  
  3. //conf.setMaster("spark://DaShuJu-040:7077") //此时,程序在Spark集群  
  4. conf.setMaster("local[4]")  


2、创建SparkContext对象和SQLContext对象

[java]  view plain  copy
  1. //创建SparkContext对象,通过传入SparkConf实例来定制Spark运行的具体参数和配置信息  
  2. val sc = new SparkContext(conf)  
  3. val sqlContext = new SQLContext(sc) //构建SQL上下文  



3、模拟实际使用的数据

[java]  view plain  copy
  1. <span style="font-family: Arial, Helvetica, sans-serif;">val bigData = Array("Spark""Spark""Hadoop""Spark""Hadoop""Spark""Spark""Hadoop""Spark""Hadoop")</span>  



4、基于提供的数据创建DataFrame

[java]  view plain  copy
  1. val bigDataRDD =  sc.parallelize(bigData)  
  2. val bigDataRDDRow = bigDataRDD.map(item => Row(item))  
  3. val structType = StructType(Array(StructField("word", StringType, true)))  
  4. val bigDataDF = sqlContext.createDataFrame(bigDataRDDRow,structType)  



5、注册成为临时表

[java]  view plain  copy
  1. bigDataDF.registerTempTable("bigDataTable")  



6、通过SQLContext注册UDF,在Scala 2.10.x版本UDF函数最多可以接受22个输入参数

[java]  view plain  copy
  1. sqlContext.udf.register("computeLength", (input: String) => input.length)  
  2. //直接在SQL语句中使用UDF,就像使用SQL自动的内部函数一样  
  3. sqlContext.sql("select word, computeLength(word) as length from bigDataTable").show  


7、通过SQLContext注册UDAF

[java]  view plain  copy
  1. sqlContext.udf.register("wordCount"new MyUDAF)  
  2. sqlContext.sql("select word,wordCount(word) as count,computeLength(word) as length" +  
  3. " from bigDataTable group by word").show()  



8、按照模板实现UDAF


[java]  view plain  copy
  1. class  MyUDAF extends UserDefinedAggregateFunction {  
  2.   // 该方法指定具体输入数据的类型  
  3.   override def inputSchema: StructType = StructType(Array(StructField("input", StringType, true)))  
  4.   //在进行聚合操作的时候所要处理的数据的结果的类型,是结束之前,缓存的中间结果的类型  
  5.   override def bufferSchema: StructType = StructType(Array(StructField("count", IntegerType, true)))  
  6.   //指定UDAF函数计算后返回的结果类型,全部聚合后的最终结果类型  
  7.   override def dataType: DataType = IntegerType  
  8.   // 确保一致性 一般用true  
  9.   override def deterministic: Boolean = true  
  10.   //在Aggregate之前每组数据的初始化结果  
  11.   override def initialize(buffer: MutableAggregationBuffer): Unit = {buffer(0) =0}  
  12.   // 在进行聚合的时候,每当有新的值进来,对分组后的聚合如何进行计算  
  13.   // 本地的聚合操作,相当于Hadoop MapReduce模型中的Combiner  
  14.   override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {  
  15.     var last_string= buffer.getString(0)
  16.     var current_string=input.getString(0) 

  17.     buffero(0)=current_string+1
  18.   }  
  19.   //最后在分布式节点进行Local Reduce完成后需要进行全局级别的Merge操作  
  20.   override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {  
  21.     buffer1(0) = buffer1.getAs[Int](0) + buffer2.getAs[Int](0)  
  22.   }  
  23.   //返回UDAF最后的计算结果  
  24.   override def evaluate(buffer: Row): Any = buffer.getAs[Int](0)  
  25. }  

注意 getAs【Int】(0)  和   getInt(0)相同



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值