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函数的更多相关文章

  1. Spark SQL中UDF和UDAF

    转载自:https://blog.csdn.net/u012297062/article/details/52227909 UDF: User Defined Function,用户自定义的函数,函数 ...

  2. Spark SQL概念学习系列之用户自定义函数

    不多说,直接上干货! 用户自定义函数 注册udf 我们可以使用Spark 支持的编程语言编写好函数,然后通过Spark SQL 内建的方法传递进来,非常便捷地注册我们自己的UDF 在Scala 和Py ...

  3. 【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用

    一.前述 SparkSQL中的UDF相当于是1进1出,UDAF相当于是多进一出,类似于聚合函数. 开窗函数一般分组取topn时常用. 二.UDF和UDAF函数 1.UDF函数 java代码: Spar ...

  4. Spark(十三)【SparkSQL自定义UDF/UDAF函数】

    目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...

  5. Databricks 第9篇:Spark SQL 基础(数据类型、NULL语义)

    Spark SQL 支持多种数据类型,并兼容Python.Scala等语言的数据类型. 一,Spark SQL支持的数据类型 整数系列: BYTE, TINYINT:表示1B的有符号整数 SHORT, ...

  6. Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)

    在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...

  7. 详解Spark sql用户自定义函数:UDF与UDAF

    UDAF = USER DEFINED AGGREGATION FUNCTION Spark sql提供了丰富的内置函数供猿友们使用,辣为何还要用户自定义函数呢?实际的业务场景可能很复杂,内置函数ho ...

  8. 【Spark篇】---SparkSql之UDF函数和UDAF函数

    一.前述 SparkSql中自定义函数包括UDF和UDAF UDF:一进一出  UDAF:多进一出 (联想Sum函数) 二.UDF函数 UDF:用户自定义函数,user defined functio ...

  9. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十五)Spark编写UDF、UDAF、Agg函数

    Spark Sql提供了丰富的内置函数让开发者来使用,但实际开发业务场景可能很复杂,内置函数不能够满足业务需求,因此spark sql提供了可扩展的内置函数. UDF:是普通函数,输入一个或多个参数, ...

随机推荐

  1. selenium中WebElement.getText()为空解决方法

    当使用getText()获取一个普通的链接文本时: <a href="http://www.baidu.com">baidu</a> 如果得到的文本只为空, ...

  2. 什么是Spring Cloud

    Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均衡.断路器.数据监控等,都可以用 ...

  3. DTD与XML Schema都是XML文档。(选择1项)

    DTD与XML Schema都是XML文档.(选择1项) A.正确 B.不正确 解答:DTD不是XML文件, schema是XML文档

  4. 如果想要跨平台,在file类下有separtor(),返回锁出平台的文件分隔符

    对于命令:File f2=new file(“d:\\abc\\789\\1.txt”) 这个命令不具备跨平台性,因为不同的OS的文件系统很不相同. 如果想要跨平台,在file类下有separtor( ...

  5. OSG 中 相交測试 模块 工作流程及原理

    主要涉及三个类: 1. osgUtil::PolytopeIntersector // 详细不同算法实现类 2. osgUtil::IntersectionVisitor //用来遍历节点树的每一个节 ...

  6. IPL和SPL的区别

    IPL是英文Initial Program Loader的简称,意为初始程序的装入程序,其主要功能为负责主板.电源.硬件初始化程序.并把SPL装入RAM空间中,当IPL损坏则只能更换字库解决否则只能换 ...

  7. mysql根据查询结果,创建表

    create table copy_materials_details (SELECT * FROM `materials_details`);

  8. 在 Linux 上管理加密密钥的最佳体验

    导读 存储 SSH 的加密秘钥和记住密码一直是一个让人头疼的问题.但是不幸的是,在当前这个充满了恶意黑客和攻击的世界中,基本的安全预防是必不可少的.对于许多普通用户来说,大多数人只能是记住密码,也可能 ...

  9. 【BZOJ3211】花神游历各国 并查集+树状数组

    [BZOJ3211]花神游历各国 Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 41 100 5 551 1 22 1 ...

  10. LAMP集群项目三 配置业务服务器

    安装MySQL 参考脚本:CentOS6.5一键安装MySQL5.5.32(源码编译) 在备份服务器上配置rsync推送任务 在备份服务器上配置  /etc/rsyncd.conf #在所有的客户端都 ...