• 2、Hive UDF编程实例


    Hive的UDF包括3种:UDF(User-Defined Function)、UDAF(User-Defined Aggregate Function)UDTF(User-Defined Table-Generating Function),Hive只支持Java编写UDF,其他的编程语言只能通过select transform转化为流来与Hive交互。

    UDF(User-Defined Function):支持一个输入产生一个输出。继承自org.apache.hadoop.hive.ql.exec.UDF,并实现evaluate方法。

    1、代码实现

    import org.apache.hadoop.hive.ql.exec.UDF;
    import org.apache.hadoop.io.Text;

    public class Lower2Upper extends UDF {

      public Text evaluate(Text text,String up_low){
        if(text==null){
          return null;
        }else if(up_low.equals("lowercase")){
          return new Text(text.toString().toLowerCase());
        }else if(up_low.equals("uppercase")){
          return new Text(text.toString().toUpperCase());
        }else{
          return null;
        }
      }

    }

    2、打包,并放到hive所在的机器

    3、进入hive的shell,用add jar命令把jar包导入到hive的环境变量中,用create temporary function as 命令基于jar包中的类创建临时函数。

    hive>add jar /home/user/lowupper.jar;
    hive>create temporary function lowupper as 'com.upit.hive.udf.Low2Upper';
    hive>select lowupper(name,'uppercase') from userinfo;

    4、销毁不再需要的函数

    hive>drop temporary function lowupper;

    注意:lowupper为临时的函数,所以每次进入都需要add jar以及create temporary操作。

    UDAF(User-Defined Aggregate Function):支持多个输入一个输出。继承org.apache.hadoop.hive.ql.exec.UDAF类,实现org.apache.hadoop.hive.ql.exec.UDAFvaluator接口。UDAFvaluator接口有5个方法,分别如下:

    • int  方法负责对中间结果实现初始化
    • iterate  接收传入的参数,并进行内部的轮转,其返回类型为boolean
    • terminaePartial  没有参数,负责返回iterate函数轮转后的数据
    • merge  接收terminatePartial的返回结果,合并接收的蹭值,返回类型为boolean
    • terminate  返回最终结果

    import org.apache.hadoop.hive.ql.exec.NumericUDAF;
    import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
    import org.apache.hadoop.hive.serde2.io.DoubleWritable;

    public class UDAFSum_Sample extends NumericUDAF {
      public static class Evaluator implements UDAFEvaluator{
        private boolean mEmpty;
        private double mSum;
        public Evaluator(){
          super();
          init();
        }
        @Override
        public void init() {
          mSum=0;
          mEmpty=true;
        }
        public boolean iterate(DoubleWritable o){
          if(o!=null){
            mSum+=o.get();
            mEmpty=false;
          }
          return true;
        }
        public DoubleWritable terminatePartial(){
          return mEmpty?null:new DoubleWritable(mSum);
        }
        public boolean merge(DoubleWritable o){
          if(o!=null){
            mSum+=o.get();
            mEmpty=false;
          }
          return true;
        }
        public DoubleWritable terminate(){
          return mEmpty?null:new DoubleWritable(mSum);
        }
      }
    }

    关于UDAF开发应注意以下几点:

    • import org.apache.hadoop.hive.ql.exec.UDAF以及org.apache.hadoop.hive.ql.exec.UDAFEvaluator包都是必需的。
    • 函数类需要继承UDAF类,内部类Evaluator实现UDAFEvaluator接口。
    • Evaluator需要实现init、iterate、terminatePartial、merge、terminate这几个函数。
    • init函数类似于构造函数,用于UDAF的初始化。
    • iterate接收传入的参数,并进行内部的轮转,其返回类型为boolean。
    • terminatePartial无参数,其为iterate函数轮转结束后返回的轮转数据,iterate和terminatePartial类似于Hadoop的Combiner.
    • merge接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean。
    • terminate返回最终的聚集函数结果。

    UDTF(User-Defined Table-Generating Function):支持一个输入多个输出。

    1、如何实现UDTF

    继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF。

    实现initialize, process, close三个方法

    UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息(返回个数,类型)。初始化完成后,会调用process方法,对传入的参数进行处理,可以通过forword()方法把结果返回。最后close()方法调用,对需要清理的方法进行清理

    2、实例

    如下代码对形如key:value;key:value;格式的字符串分拆成key,value,返回结果为key, value两个字段

    import java.util.ArrayList;
    import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
    import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
    import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
    import org.apache.hadoop.hive.ql.metadata.HiveException;
    import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
    import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
    import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
    import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

    public class ExplodeMap extends GenericUDTF {
      @Override
      public void close() throws HiveException {}

      @Override
      public StructObjectInspector initialize(ObjectInspector[] args)throws UDFArgumentException {
        if (args.length != 1) {
          throw new UDFArgumentLengthException("ExplodeMap takes only one argument");
        }
        if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
          throw new UDFArgumentException("ExplodeMap takes string as a parameter");
        }
        ArrayList<String> fieldNames = new ArrayList<String>();
        ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
        fieldNames.add("col1");
        fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        fieldNames.add("col2");
        fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
      }

      @Override
      public void process(Object[] args) throws HiveException {
        String input = args[0].toString();
        String[] test = input.split(";");
        for (int i = 0; i < test.length; i++) {
          try {
            String[] result = test[i].split(":");
            forward(result);
          } catch (Exception e) {
            continue;
          }
        }
      }
    }

    3、 如何使用UDTF

    3.1、在select中使用UDTF

    select explode_map(properties) as (col1,col2) from my_table

    不可以添加其他字段使用:select a, explode_map(properties) as (col1,col2) from my_table

    不可以嵌套调用:select explode_map(explode_map(properties)) from my_table

    不可以和group by/cluster by/distribute by/sort by一起使用:select explode_map(properties) as (col1,col2) from src group by col1, col2

    3.2、结合lateral view使用

    select src.id, mytable.col1, mytable.col2 from src lateral view explode_map(properties) mytable as col1, col2;

     此方法更为方便日常使用。执行过程相当于单独执行了两次抽取,然后union到一个表里。

    4、总结

     使用lateral view之后,那么col1和col2相当于普通的列,可以参与查询,计算

  • 相关阅读:
    友元函数和友元类
    分别用C和C++来实现一个链栈
    static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
    四种对象生存期和作用域、static 用法总结
    static 成员变量、static 成员函数、类/对象的大小
    深拷贝与浅拷贝、空类与空数组
    初始化列表(const和引用成员)、拷贝构造函数
    构造函数、析构函数、赋值与初始化、explicit关键字
    类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等
    引用、数组引用与指针引用、内联函数inline、四种类型转换运算符
  • 原文地址:https://www.cnblogs.com/netbloomy/p/6742057.html
Copyright © 2020-2023  润新知