zoukankan      html  css  js  c++  java
  • hive UDF 编程

    UDF的定义

    • UDF(User-Defined Functions)即是用户定义的hive函数。hive自带的函数并不能完全满足业务需求,这时就需要我们自定义函数了

    UDF的分类

    1. UDF:one to one,进来一个出去一个,row mapping。是row级别操作,如:upper、substr函数
    2. UDAF:many to one,进来多个出去一个,row mapping。是row级别操作,如sum/min。
    3. UDTF:one to many ,进来一个出去多个。如alteral view与explode

     自定义UDF

    引入maven依赖

    <dependency>
                <groupId>org.apache.hive</groupId>
                <artifactId>hive-exec</artifactId>
                <version>2.3.0</version>
    </dependency>

    实现抽象类GenericUDF

    该类的全路径为:org.apache.hadoop.hive.ql.udf.generic.GenericUDF

     1)抽象类GenericUDF解释
    GenericUDF类如下:

    public abstract class GenericUDF implements Closeable {
         ...
         /* 实例化后initialize方法只会调用一次
            - 参数arguments即udf接收的参数列表对应的objectinspector
            - 返回的ObjectInspector对象就是udf返回值的对应的objectinspector
          initialize方法中往往做的工作是检查一下arguments是否和你udf需要的参数个数以及类型是否匹配。
         */
         
         public abstract ObjectInspector initialize(ObjectInspector[] arguments)
          throws UDFArgumentException;
         ...
          // 真正的udf逻辑在这里实现
          // - 参数arguments即udf函数输入数据,这个数组的长度和initialize的参数长度一样
          // 
          public abstract Object evaluate(DeferredObject[] arguments)
          throws HiveException;
    }

    关于ObjectInspector,HIVE在传递数据时会包含数据本身以及对应的ObjectInspector,ObjectInspector中包含数据类型信息,通过oi去解析获得数据。

    2) 实例

    public class DateFeaker extends GenericUDF{
        private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        
          private transient ObjectInspectorConverters.Converter[] converters;
    
          @Override
          public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
            if (arguments.length != 2) {
              throw new UDFArgumentLengthException(
                  "The function date_util(startdate,enddate) takes exactly 2 arguments.");
            }
    
            converters = new ObjectInspectorConverters.Converter[arguments.length];
            for (int i = 0; i < arguments.length; i++) {
              converters[i] = ObjectInspectorConverters.getConverter(arguments[i],
                  PrimitiveObjectInspectorFactory.writableStringObjectInspector);
            }
    
            return ObjectInspectorFactory
                .getStandardListObjectInspector(PrimitiveObjectInspectorFactory
                    .writableStringObjectInspector);
          }
          
    
    
        @Override
        public Object evaluate(DeferredObject[] arguments) throws HiveException {
            if (arguments.length != 2) {
                  throw new UDFArgumentLengthException(
                      "The function date_util(startdate,enddate) takes exactly 2 arguments.");
                }
            
            ArrayList<Text> temp = new ArrayList<Text>();
            
            if (arguments[0].get() == null || arguments[1].get() == null) {
                return null;
             }
            System.out.println(converters[0].getClass().getName());
            System.out.println(arguments[0].getClass().getName());
            Text startDate = (Text) converters[0].convert(arguments[0].get());
            Text endDate = (Text) converters[1].convert(arguments[1].get());
            Date start;
            try {
                start = sdf.parse(startDate.toString());
            } catch (ParseException e) {
                e.printStackTrace();
                throw new UDFArgumentException(
                        "The First Argument does not match the parttern yyyy-MM-dd "+arguments[0].get());
            }
            Date end;
            try {
                end = sdf.parse(endDate.toString());
            } catch (ParseException e) {
                e.printStackTrace();
                throw new UDFArgumentException(
                        "The Second Argument does not match the parttern yyyy-MM-dd "+arguments[1].get());
            }
            Calendar  c = Calendar.getInstance();
            while(start.getTime()<=end.getTime()){
                temp.add(new Text(sdf.format(start)));
                c.setTime(start);
                c.add(Calendar.DATE, 1);
                start = c.getTime();
            }
            return temp;
        }
    
        @Override
        public String getDisplayString(String[] children) {
            assert (children.length == 2);
            return getStandardDisplayString("date_util", children);
        }

    3)部署UDF函数

    上传jar包

    [hadoop@hadoop001 lib]$hadoop fs -put  g6-hadoop-1.0.jar hdfs://chd:8020/user
    • 注意:如果jar包是上传到$HIVE_HOME/lib/目录以下,就不需要执行add命令了

    添加jar包到hive  

    • 语法:add jar +jar包所在的目录/jar包名字
    hive> add jar /home/hadoop/data/hive/g6-hadoop-1.0.jar;

    在hive中创建UDF函数

    1)创建临时函数    -----只对当前黑窗口有效

    CREATE TEMPORARY FUNCTION function_name AS class_name;   
    
    function_name函数名                        
    
    *******class_name 类路径,包名+类名*********   这里就是你写的UDF函数的第一行的package后边的东西然后在加个点加个类的名字

    删除临时函数 :

    • 语法:DROP TEMPORARY FUNCTION [IF EXISTS] function_name; 

    创建永久函数

    • 语法:
    CREATE TEMPORARY FUNCTION function_name AS class_name USING JAR path;
    
    function_name函数名                        
    
    class_name 类路径,
    
    包名+类名 
    
    path jar包hdfs路径

    实例

    CREATE FUNCTION HelloUDF AS 'org.apache.hadoop.hive.ql.udf.HelloUDF'
    
    USING JAR 'hdfs://hadoop001:9000/lib/g6-hadoop-1.0.jar';
    
    #测试 hive> select HelloUDF("17") ;
    
    OK hello:17

    4)推荐比较全的实例

    git地址:https://github.com/tchqiq/HiveUDF/tree/master/src/main/java/cn/com/diditaxi/hive/cf

  • 相关阅读:
    Aop——面向切面编程
    认识界上最流行的Api框架——swagger
    手把手SSM框架实战
    面试题
    重新拾起JavaSE的日子
    使用IntelliJ IDEA创建第一个Maven项目
    Java面试必考题
    Vue项目——去哪网(首页部分)
    Vue项目的准备
    vue.js ③
  • 原文地址:https://www.cnblogs.com/yyy-blog/p/13601906.html
Copyright © 2011-2022 走看看