zoukankan      html  css  js  c++  java
  • 简述UDF/UDAF/UDTF是什么,各自解决问题及应用场景

    UDF

    • User-Defined-Function 自定义函数 、一进一出;

    • 背景

      • 系统内置函数无法解决实际的业务问题,需要开发者自己编写函数实现自身的业务实现诉求。
      • 应用场景非常多,面临的业务不同导致个性化实现很多,故udf很需要。
    • 意义

      • 函数扩展得到解决,极大丰富了可定制化的业务需求。
      • IO要求-要解决的问题
        • in:out=1:1,只能输入一条记录当中的数据,同时返回一条处理结果。
        • 属于最常见的自定义函数,像cos,sin,substring,indexof等均是如此要求
    • 实现步骤(Java创建自定义UDF类)

      • 自定义一个java类
      • 继承UDF类
      • 重写evaluate方法
      • 打包类所在项目成一个all-in-one的jar包并上传到hive所在机器
      • 在hive中执行add jar操作,将jar加载到classpath中。
      • 在hive中创建模板函数,使得后边可以使用该函数名称调用实际的udf函数
      • hive sql中像调用系统函数一样使用udf函数
    • 代码实现

      • 功能要求:实现当输入字符串超过2个字符的时候,多余的字符以”…”来表示。
      • 如“12”则返回“12”,如“123”返回“12…”
      • 自定义类、继承UDF、重写evaluate方法已在代码中体现
    import org.apache.hadoop.hive.ql.exec.UDF;
    /*
     * 功能:实现当输入字符串超过2个字符的时候,多余的字符以"..."来表示。
     * 输入/输出:* 如“12”则返回“12”,如“123”返回“12..."
     */
    public class ValueMaskUDF extends UDF{
           public String evaluate(String input,int maxSaveStringLength,String replaceSign) {
                 if(input.length()<=maxSaveStringLength){
                        return input;
                 }
                 return input.substring(0,maxSaveStringLength)+replaceSign;
           }
           public static void main(String[] args) {
                 System.out.println(new ValueMaskUDF().evaluate("河北省",2,"..."));;
           }
    }
    

    UDAF

    • 自定义udaf函数self_count,实现系统udaf count的功能

    • Input/Output要求-要解决的问题

      • in:out=n:1,即接受输入N条记录当中的数据,同时返回一条处理结果。
      • 属于最常见的自定义函数,像count,sum,avg,max等均是如此要求
    • 实现步骤

      • 自定义一个java类
      • 继承UDAF类
      • 内部定义一个静态类,实现UDAFEvaluator接口
      • 实现方法init,iterate,terminatePartial,merge,terminate,共5个方法. 详见下图
      • 在hive中执行add jar操作,将jar加载到classpath中。
      • 在hive中创建模板函数,使得后边可以使用该函数名称调用实际的udf函数
      • hive sql中像调用系统函数一样使用udaf函数


         
        Hive_UDAF五个方法.png
    • 业务测试

    输入:


     
    输入.png

    输出:


     
    输出.png
    • UDAF代码开发
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import org.apache.hadoop.hive.ql.exec.UDAF;
    import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
    import org.apache.log4j.Logger;
    /**
    * 实现多条数据合并成一条数据
    */
    // 主类继承UDAF
    public class StudentScoreAggUDAF extends UDAF {
        // 日志对象初始化
        public static Logger logger = Logger.getLogger(StudentScoreAggUDAF.class);
        // 静态类实现UDAFEvaluator
        public static class Evaluator implements UDAFEvaluator {
            // 设置成员变量,存储每个统计范围内的总记录数
            private Map<String, String> courseScoreMap;
    
            //初始化函数,map和reduce均会执行该函数,起到初始化所需要的变量的作用
            public Evaluator() {
                init();
            }
            // 初始化函数间传递的中间变量
            public void init() {
                courseScoreMap = new HashMap<String, String>();
            }
    
             //map阶段,返回值为boolean类型,当为true则程序继续执行,当为false则程序退出  
            public boolean iterate(String course, String score) {
                if (course == null || score == null) {
                    return true;
                }
                courseScoreMap.put(course, score);
                return true;
            }
             /**
             * 类似于combiner,在map范围内做部分聚合,将结果传给merge函数中的形参mapOutput  
             * 如果需要聚合,则对iterator返回的结果处理,否则直接返回iterator的结果即可
             */
            public Map<String, String> terminatePartial() {
                return courseScoreMap;
            }
             // reduce 阶段,用于逐个迭代处理map当中每个不同key对应的 terminatePartial的结果
            public boolean merge(Map<String, String> mapOutput) {
                this.courseScoreMap.putAll(mapOutput);
                return true;
            }
            // 处理merge计算完成后的结果,即对merge完成后的结果做最后的业务处理
            public String terminate() {
                return courseScoreMap.toString();
            }
        }
    }
    

    测试sql语句

    select id,username,score_agg(course,score) from student_score group by id,username;
    

    UDTF

    • User-Defined Table-Generating Functions
    • 要解决一行输入多行输出的问题,问题的应用场景不少
    • 用udtf解决一行输入多行输出的不多,往往被lateral view explode+udf等替代实现,比直接用udtf会更简单、直接一些
  • 相关阅读:
    Android杂谈ubuntu系统下adb连接小米2
    Android UI设计ListView的页脚(footer)的使用
    Android杂谈关于Android的nodpi,xhdpi,hdpi,mdpi,ldpi
    ”该证书已被签发机构吊销“错误解决方案
    Android杂谈RelativeLayout中的baseline是什么?
    ubuntu下git更改默认编辑器
    Android UI设计ListView Item的OnItemLongClickListener同时监听两种事件
    Android UI设计ListView的item选中效果
    Ubuntu下ssh服务器文件操作命令
    ubuntu下emacs的配置(cedit,ecb)
  • 原文地址:https://www.cnblogs.com/sx66/p/12039552.html
Copyright © 2011-2022 走看看