写hive的udf函数

来源:互联网 发布:淘宝店铺突然没流量 编辑:程序博客网 时间:2024/06/05 22:30

最近感受了Hive的udf函数的强大威力了,不仅可以使用很多已经有的udf函数,还可以自己定义符合业务场景的udf函数,下面就说一下如何写udf/udaf/udtf函数,算是一个入门介绍吧。

First, you need to create a new class that extends UDF, with one or more methods named evaluate.

[html] view plain copy
  1. package com.example.hive.udf;  
  2.   
  3. import org.apache.hadoop.hive.ql.exec.UDF;  
  4. import org.apache.hadoop.io.Text;  
  5.   
  6. public final class Lower extends UDF {  
  7.   public Text evaluate(final Text s) {  
  8.     if (s == null) { return null; }  
  9.     return new Text(s.toString().toLowerCase());  
  10.   }  
  11. }  

After compiling your code to a jar, you need to add this to the hive classpath.

[html] view plain copy
  1. add jar my_jar.jar;  

Once hive is started up with your jars in the classpath, the final step is to register your function

[html] view plain copy
  1. create temporary function my_lower as 'com.example.hive.udf.Lower';  

上面主要描述了实现一个udf的过程,首先自然是实现一个UDF函数,然后编译为jar并加入到hive的classpath中,最后创建一个临时变量名字让hive中调用。


下面这个表格可以更加清晰的看出udf/udaf/udtf之间的区别

Show几个例子:

1) UDF (参考:http://svn.apache.org/repos/asf/hive/trunk/contrib/src/java/org/apache/hadoop/hive/contrib/udf/)

[html] view plain copy
  1. package org.apache.hadoop.hive.contrib.udf.example;  
  2.   
  3. import org.apache.hadoop.hive.ql.exec.UDF;  
  4.   
  5. /**  
  6.  * UDFExampleAdd.  
  7.  *  
  8.  */  
  9. public class UDFExampleAdd extends UDF {  
  10.   
  11.   public Integer evaluate(Integer... a) {  
  12.     int total = 0;  
  13.     for (Integer element : a) {  
  14.       if (element != null) {  
  15.         total += element;  
  16.       }  
  17.     }  
  18.     return total;  
  19.   }  
  20.   
  21.   public Double evaluate(Double... a) {  
  22.     double total = 0;  
  23.     for (Double element : a) {  
  24.       if (element != null) {  
  25.         total += element;  
  26.       }  
  27.     }  
  28.     return total;  
  29.   }  
  30.   
  31. }  

2)UDAF(http://svn.apache.org/repos/asf/hive/trunk/contrib/src/java/org/apache/hadoop/hive/contrib/udaf/

[html] view plain copy
  1. package org.apache.hadoop.hive.contrib.udaf.example;  
  2.   
  3. import org.apache.hadoop.hive.ql.exec.UDAF;  
  4. import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;  
  5.   
  6. /**  
  7.  * This is a simple UDAF that calculates average.  
  8.  *   
  9.  * It should be very easy to follow and can be used as an example for writing  
  10.  * new UDAFs.  
  11.  *   
  12.  * Note that Hive internally uses a different mechanism (called GenericUDAF) to  
  13.  * implement built-in aggregation functions, which are harder to program but  
  14.  * more efficient.  
  15.  *   
  16.  */  
  17. public final class UDAFExampleAvg extends UDAF {  
  18.   
  19.   /**  
  20.    * The internal state of an aggregation for average.  
  21.    *   
  22.    * Note that this is only needed if the internal state cannot be represented  
  23.    * by a primitive.  
  24.    *   
  25.    * The internal state can also contains fields with types like  
  26.    * ArrayList<String> and HashMap<String,Double> if needed.  
  27.    */  
  28.   public static class UDAFAvgState {  
  29.     private long mCount;  
  30.     private double mSum;  
  31.   }  
  32.   
  33.   /**  
  34.    * The actual class for doing the aggregation. Hive will automatically look  
  35.    * for all internal classes of the UDAF that implements UDAFEvaluator.  
  36.    */  
  37.   public static class UDAFExampleAvgEvaluator implements UDAFEvaluator {  
  38.   
  39.     UDAFAvgState state;  
  40.   
  41.     public UDAFExampleAvgEvaluator() {  
  42.       super();  
  43.       state = new UDAFAvgState();  
  44.       init();  
  45.     }  
  46.   
  47.     /**  
  48.      * Reset the state of the aggregation.  
  49.      */  
  50.     public void init() {  
  51.       state.mSum = 0;  
  52.       state.mCount = 0;  
  53.     }  
  54.   
  55.     /**  
  56.      * Iterate through one row of original data.  
  57.      *   
  58.      * The number and type of arguments need to the same as we call this UDAF  
  59.      * from Hive command line.  
  60.      *   
  61.      * This function should always return true.  
  62.      */  
  63.     public boolean iterate(Double o) {  
  64.       if (o != null) {  
  65.         state.mSum += o;  
  66.         state.mCount++;  
  67.       }  
  68.       return true;  
  69.     }  
  70.   
  71.     /**  
  72.      * Terminate a partial aggregation and return the state. If the state is a  
  73.      * primitive, just return primitive Java classes like Integer or String.  
  74.      */  
  75.     public UDAFAvgState terminatePartial() {  
  76.       // This is SQL standard - average of zero items should be null.  
  77.       return state.mCount == 0 ? null : state;  
  78.     }  
  79.   
  80.     /**  
  81.      * Merge with a partial aggregation.  
  82.      *   
  83.      * This function should always have a single argument which has the same  
  84.      * type as the return value of terminatePartial().  
  85.      */  
  86.     public boolean merge(UDAFAvgState o) {  
  87.       if (o != null) {  
  88.         state.mSum += o.mSum;  
  89.         state.mCount += o.mCount;  
  90.       }  
  91.       return true;  
  92.     }  
  93.   
  94.     /**  
  95.      * Terminates the aggregation and return the final result.  
  96.      */  
  97.     public Double terminate() {  
  98.       // This is SQL standard - average of zero items should be null.  
  99.       return state.mCount == 0 ? null : Double.valueOf(state.mSum  
  100.           / state.mCount);  
  101.     }  
  102.   }  
  103.   
  104.   private UDAFExampleAvg() {  
  105.     // prevent instantiation  
  106.   }  
  107.   
  108. }  

3)UDTF(http://svn.apache.org/repos/asf/hive/trunk/contrib/src/java/org/apache/hadoop/hive/contrib/udtf/

[html] view plain copy
  1. package org.apache.hadoop.hive.contrib.udtf.example;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.hadoop.hive.ql.exec.Description;  
  7. import org.apache.hadoop.hive.ql.exec.UDFArgumentException;  
  8. import org.apache.hadoop.hive.ql.metadata.HiveException;  
  9. import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;  
  10. import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;  
  11. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;  
  12. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;  
  13. import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;  
  14.   
  15. /**  
  16.  * GenericUDTFExplode2.  
  17.  *  
  18.  */  
  19. @Description(name = "explode2",  
  20.     value = "_FUNC_(a) - like explode, but outputs two identical columns (for testing purposes)")  
  21. public class GenericUDTFExplode2 extends GenericUDTF {  
  22.   
  23.   ListObjectInspector listOI = null;  
  24.   
  25.   @Override  
  26.   public void close() throws HiveException {  
  27.   }  
  28.   
  29.   @Override  
  30.   public StructObjectInspector initialize(ObjectInspector[] args)  
  31.       throws UDFArgumentException {  
  32.   
  33.     if (args.length != 1) {  
  34.       throw new UDFArgumentException("explode() takes only one argument");  
  35.     }  
  36.   
  37.     if (args[0].getCategory() != ObjectInspector.Category.LIST) {  
  38.       throw new UDFArgumentException("explode() takes an array as a parameter");  
  39.     }  
  40.     listOI = (ListObjectInspector) args[0];  
  41.   
  42.     ArrayList<String> fieldNames = new ArrayList<String>();  
  43.     ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();  
  44.     fieldNames.add("col1");  
  45.     fieldNames.add("col2");  
  46.     fieldOIs.add(listOI.getListElementObjectInspector());  
  47.     fieldOIs.add(listOI.getListElementObjectInspector());  
  48.     return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,  
  49.         fieldOIs);  
  50.   }  
  51.   
  52.   Object forwardObj[] = new Object[2];  
  53.   
  54.   @Override  
  55.   public void process(Object[] o) throws HiveException {  
  56.   
  57.     List<?> list = listOI.getList(o[0]);  
  58.     for (Object r : list) {  
  59.       forwardObj[0] = r;  
  60.       forwardObj[1] = r;  
  61.       forward(forwardObj);  
  62.     }  
  63.   }  
  64.   
  65.   @Override  
  66.   public String toString() {  
  67.     return "explode";  
  68.   }  
  69. }  
原创粉丝点击