Spark Sql的UDF和UDAF函数
Spark Sql提供了丰富的内置函数供猿友们使用,辣为何还要用户自定义函数呢?实际的业务场景可能很复杂,内置函数hold不住,所以spark sql提供了可扩展的内置函数接口:哥们,你的业务太变态了,我满足不了你,自己按照我的规范去定义一个sql函数,该怎么折腾就怎么折腾!
这里还是先以Scala实现一个简单的hello world级别的小样为例,来体验udf与udaf的使用好了。
问题
将如下数组:
val bigData = Array("Spark","Hadoop","Flink","Spark","Hadoop","Flink",
"Spark","Hadoop","Flink","Spark","Hadoop","Flink")
中的字符分组聚合并计算出每个字符的长度及字符出现的个数。正常结果
如下:
+------+-----+------+
| name|count|length|
+------+-----+------+
| Spark| | |
| Flink| | |
|Hadoop| | |
+------+-----+------+
注:‘spark’ 这个字符的长度为5 ,共出现了4次。
分析
- 自定义个一个求字符串长度的函数
自定义的sql函数,与scala中的普通函数一样,只不过在使用上前者需要先在sqlContext中进行注册。 - 自定义一个聚合函数
按照字符串名称分组后,调用自定义的聚合函数实现累加。
啊,好抽象,直接看代码吧!
代码
package com.hand.datasafe import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{Row, SQLContext, SparkSession}
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.types.StructField
import org.apache.spark.sql.types.StringType /**
* Spark SQL UDAF:user defined aggregation function
* UDF: 函数的输入是一条具体的数据记录,实现上讲就是普通的scala函数-只不过需要注册
* UDAF:用户自定义的聚合函数,函数本身作用于数据集合,能够在具体操作的基础上进行自定义操作
*/
object SparkSQLUDF { def main(args: Array[String]): Unit = { val spark = SparkSession.builder().appName("datasafe").master("local").getOrCreate() val bigData = Array("Spark", "Hadoop", "Flink", "Spark", "Hadoop", "Flink", "Spark", "Hadoop", "Flink", "Spark", "Hadoop", "Flink")
val bigDataRDD = spark.sparkContext.parallelize(bigData) val bigDataRowRDD: RDD[Row] = bigDataRDD.map(line => Row(line))
val structType = StructType(Array(StructField("name", StringType, true)))
val bigDataDF = spark.createDataFrame(bigDataRowRDD, structType)
bigDataDF.printSchema()
bigDataDF.createTempView("bigDataTable") /*
* 通过saprk注册UDF,在scala2.1.x版本UDF函数最多可以接受22个输入参数
*/
spark.udf.register("computeLength", (input: String) => input.length)
spark.sql("select name,computeLength(name) as length from bigDataTable").show //while(true){} spark.udf.register("wordCount", new MyUDAF)
spark.sql("select name,wordCount(name) as count,computeLength(name) as length from bigDataTable group by name ").show
spark.sql("select name,wordCount(name) as count,computeLength(name) as length from bigDataTable group by name ").printSchema() }
}
package com.hand.datasafe import org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._ /**
* 用户自定义函数
*/
class MyUDAF extends UserDefinedAggregateFunction
{
/**
* 指定具体的输入数据的类型
* 自段名称随意:Users can choose names to identify the input arguments - 这里可以是“name”,或者其他任意串
*/
override def inputSchema:StructType = StructType(Array(StructField("name",StringType,true))) /**
* 在进行聚合操作的时候所要处理的数据的中间结果类型
*/
override def bufferSchema:StructType = StructType(Array(StructField("count",IntegerType,true))) /**
* 返回类型
*/
override def dataType:DataType = IntegerType /**
* whether given the same input,
* always return the same output
* true: yes
*/
override def deterministic:Boolean = true /**
* Initializes the given aggregation buffer
*/
override def initialize(buffer:MutableAggregationBuffer):Unit = {buffer()=} /**
* 在进行聚合的时候,每当有新的值进来,对分组后的聚合如何进行计算
* 本地的聚合操作,相当于Hadoop MapReduce模型中的Combiner
*/
override def update(buffer:MutableAggregationBuffer,input:Row):Unit={
buffer() = buffer.getInt()+
} /**
* 最后在分布式节点进行local reduce完成后需要进行全局级别的merge操作
*/
override def merge(buffer1:MutableAggregationBuffer,buffer2:Row):Unit={
buffer1() = buffer1.getInt()+buffer2.getInt()
} /**
* 返回UDAF最后的计算结果
*/
override def evaluate(buffer:Row):Any = buffer.getInt()
}
总结
呼叫spark大神升级udaf实现
为了自己实现一个sql聚合函数,我需要继承UserDefinedAggregateFunction并实现8个抽象方法!8个方法啊!what’s a disaster ! 然而,要想在sql中完成符合特定业务场景的聚合类(a = aggregation)功能,就得udaf。
怎么理解MutableAggregationBuffer呢?就是存储中间结果的,聚合就意味着多条记录的累加等操作。
Spark Sql的UDF和UDAF函数的更多相关文章
- Spark SQL中UDF和UDAF
转载自:https://blog.csdn.net/u012297062/article/details/52227909 UDF: User Defined Function,用户自定义的函数,函数 ...
- Spark SQL概念学习系列之用户自定义函数
不多说,直接上干货! 用户自定义函数 注册udf 我们可以使用Spark 支持的编程语言编写好函数,然后通过Spark SQL 内建的方法传递进来,非常便捷地注册我们自己的UDF 在Scala 和Py ...
- 【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用
一.前述 SparkSQL中的UDF相当于是1进1出,UDAF相当于是多进一出,类似于聚合函数. 开窗函数一般分组取topn时常用. 二.UDF和UDAF函数 1.UDF函数 java代码: Spar ...
- Spark(十三)【SparkSQL自定义UDF/UDAF函数】
目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...
- Databricks 第9篇:Spark SQL 基础(数据类型、NULL语义)
Spark SQL 支持多种数据类型,并兼容Python.Scala等语言的数据类型. 一,Spark SQL支持的数据类型 整数系列: BYTE, TINYINT:表示1B的有符号整数 SHORT, ...
- Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- 详解Spark sql用户自定义函数:UDF与UDAF
UDAF = USER DEFINED AGGREGATION FUNCTION Spark sql提供了丰富的内置函数供猿友们使用,辣为何还要用户自定义函数呢?实际的业务场景可能很复杂,内置函数ho ...
- 【Spark篇】---SparkSql之UDF函数和UDAF函数
一.前述 SparkSql中自定义函数包括UDF和UDAF UDF:一进一出 UDAF:多进一出 (联想Sum函数) 二.UDF函数 UDF:用户自定义函数,user defined functio ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十五)Spark编写UDF、UDAF、Agg函数
Spark Sql提供了丰富的内置函数让开发者来使用,但实际开发业务场景可能很复杂,内置函数不能够满足业务需求,因此spark sql提供了可扩展的内置函数. UDF:是普通函数,输入一个或多个参数, ...
随机推荐
- IDEA 中 右键新建时,没有新建class的解决方案
今天在用IDEA新建包后,因为我新建的包名是userprivman-data这样的包,然后导致右键后没法新建类,并且在新建包名的时候就提示:不合法的包名,可能不会新建类 然后右键单击包名,发现没有新建 ...
- springboot 完整企业项目搭建实记
昨天搭建ssm框架时突然想到可以搭建springboot来完美解决配置复杂的问题,今天学习了一下springboot的搭建,在此记录一下搭建的过程和踩过的坑 这里给自己定一个该框架搭建完成的目标,如下 ...
- Virtual Box下安装Oracle Linux 6.3
Oracle Linux 6.3已经公布快2年了,其功能有非常大的提升,增强了KVM,文件卷的在线resizing,LVM支持 raid4, 5, 6.支持很多其它的虚拟CPU数以及更大内存,详细能够 ...
- Visual Studio Code调试node.js:无法在PATH上找到运行时的node
首先,环境变量Path中加入nodejs的路径: 验证nodejs是否已经加入环境变量: 接着,重新启动Visual Studio Code, 试一下,是不是好了~ 附录:Visual Studi ...
- C语言数组元素的查询
在实际开发中,经常需要查询数组中的元素.例如,学校为每位同学分配了一个唯一的编号,现在有一个数组,保存了实验班所有同学的编号信息,如果有家长想知道他的孩子是否进入了实验班,只要提供孩子的编号就可以,如 ...
- ORA-01078错误解决办法
ORA-01078: failure in processing system parameters & LRM-00109: could not open parameter file 安装 ...
- IOS模拟器
IOS模拟器 目录 概述 实用操作 概述 实用操作 快速删除大量程序的方式 菜单栏 -> Reset Contain And Settings 或者:直接删除模拟器应用里面的想要去除的应用程序的 ...
- 【BZOJ1009】[HNOI2008]GT考试 next数组+矩阵乘法
[BZOJ1009][HNOI2008]GT考试 Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的 ...
- Android中的TextView实现多行显示省略号以及下划线的实现
android:lines="2" android:ellipsize="end" 显示两行,多余部分…显示 textView.getPaint().setFl ...
- SSH电力项目一 搭建Hibernate框架
Hibernate所需要的基本文件: ElectText.java ElecText.hbm.xml hibernate.cfg.xml 第一步:创建测试表Elec_Text: create tabl ...