Hive UDF开发

简介:

HIVE允许用户使用UDF(user defined function)对数据进行处理。
用户可以使用‘show functions’ 查看function list,可以使用'describe function function-name'查看函数说明。

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

  1. hive> show functions;  

  2. OK  

  3. !  

  4. !=  

  5. ......  

  6. Time taken: 0.275 seconds  

  7. hive> desc function substr;  

  8. OK  

  9. substr(str, pos[, len]) - returns the substring of str that starts at pos and is of length len orsubstr(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len  

  10. Time taken: 0.095 seconds  


hive提供的build-in函数包括以下几类:
1. 关系操作符:包括 = 、 <> 、 <= 、>=等
2. 算数操作符:包括 + 、 - 、 *、/等
3. 逻辑操作符:包括AND 、 && 、 OR 、 || 等
4. 复杂类型构造函数:包括map、struct、create_union等
5. 复杂类型操作符:包括A[n]、Map[key]、S.x
6. 数学操作符:包括ln(double a)、sqrt(double a)等
7. 集合操作符:包括size(Array<T>)、sort_array(Array<T>)等
8. 类型转换函数: binary(string|binary)、cast(expr as <type>)
9. 日期函数:包括from_unixtime(bigint unixtime[, string format])、unix_timestamp()等
10.条件函数:包括if(boolean testCondition, T valueTrue, T valueFalseOrNull)等
11. 字符串函数:包括acat(string|binary A, string|binary B...)等
12. 其他:xpath、get_json_objectscii(string str)、con

编写Hive UDF有两种方式:
1. extends UDF , 重写evaluate方法
2. extends GenericUDF,重写initialize、getDisplayString、evaluate方法


编写UDF代码实例(更多例子参考https://svn.apache.org/repos/asf/hive/tags/release-0.8.1/ql/src/java/org/apache/hadoop/hive/ql/udf/):
功能:大小转小写
ToLowerCase.java:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

  1. package test.udf;  

  2.   

  3. import org.apache.hadoop.hive.ql.exec.UDF;  

  4. import org.apache.hadoop.io.Text;  

  5.   

  6. public class ToLowerCase extends UDF {  

  7.     public Text evaluate(final Text s) {  

  8.         if (s == null) { return null; }  

  9.         return new Text(s.toString().toLowerCase());  

  10.     }  

  11. }  


功能:计算array中去重后元素个数
UDFArrayUniqElementNumber .java

[java] view plaincopy在CODE上查看代码片派生到我的代码片

  1. package test.udf;  

  2. import org.apache.hadoop.hive.ql.exec.Description;  

  3. import org.apache.hadoop.hive.ql.exec.UDFArgumentException;  

  4. import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;  

  5. import org.apache.hadoop.hive.ql.metadata.HiveException;  

  6. import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;  

  7. import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;  

  8. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;  

  9. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;  

  10. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;  

  11. import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;  

  12. import org.apache.hadoop.io.IntWritable;  

  13.   

  14. /** 

  15.  * UDF: 

  16.  * Get nubmer of objects with duplicate elements eliminated 

  17.  * @author xiaomin.zhou 

  18.  */  

  19. @Description(name = "array_uniq_element_number", value = "_FUNC_(array) - Returns nubmer of objects with duplicate elements eliminated.", extended = "Example:\n"  

  20.                 + "  > SELECT _FUNC_(array(1, 2, 2, 3, 3)) FROM src LIMIT 1;\n" + "  3")  

  21. public class UDFArrayUniqElementNumber extends GenericUDF {  

  22.   

  23.         private static final int ARRAY_IDX = 0;  

  24.         private static final int ARG_COUNT = 1// Number of arguments to this UDF  

  25.         private static final String FUNC_NAME = "ARRAY_UNIQ_ELEMENT_NUMBER"// External Name  

  26.   

  27.         private ListObjectInspector arrayOI;  

  28.         private ObjectInspector arrayElementOI;  

  29.         private final IntWritable result = new IntWritable(-1);  

  30.   

  31.         public ObjectInspector initialize(ObjectInspector[] arguments)  

  32.                         throws UDFArgumentException {  

  33.   

  34.                 // Check if two arguments were passed  

  35.                 if (arguments.length != ARG_COUNT) {  

  36.                         throw new UDFArgumentException("The function " + FUNC_NAME  

  37.                                         + " accepts " + ARG_COUNT + " arguments.");  

  38.                 }  

  39.   

  40.                 // Check if ARRAY_IDX argument is of category LIST  

  41.                 if (!arguments[ARRAY_IDX].getCategory().equals(Category.LIST)) {  

  42.                         throw new UDFArgumentTypeException(ARRAY_IDX, "\""  

  43.                                         + org.apache.hadoop.hive.serde.Constants.LIST_TYPE_NAME  

  44.                                         + "\" " + "expected at function ARRAY_CONTAINS, but "  

  45.                                         + "\"" + arguments[ARRAY_IDX].getTypeName() + "\" "  

  46.                                         + "is found");  

  47.                 }  

  48.   

  49.                 arrayOI = (ListObjectInspector) arguments[ARRAY_IDX];  

  50.                 arrayElementOI = arrayOI.getListElementObjectInspector();  

  51.   

  52.                 return PrimitiveObjectInspectorFactory.writableIntObjectInspector;  

  53.         }  

  54.   

  55.         public IntWritable evaluate(DeferredObject[] arguments)  

  56.                         throws HiveException {  

  57.   

  58.                 result.set(0);  

  59.   

  60.                 Object array = arguments[ARRAY_IDX].get();  

  61.                 int arrayLength = arrayOI.getListLength(array);  

  62.                 if (arrayLength <= 1) {  

  63.                         result.set(arrayLength);  

  64.                         return result;  

  65.                 }  

  66.   

  67.                 //element compare; Algorithm complexity: O(N^2)  

  68.                 int num = 1;   

  69.                 int i, j;   

  70.                 for(i = 1; i < arrayLength; i++)  

  71.                 {  

  72.                         Object listElement = arrayOI.getListElement(array, i);  

  73.                         for(j = i - 1; j >= 0; j--)  

  74.                         {  

  75.                                 if (listElement != null) {  

  76.                                         Object tmp = arrayOI.getListElement(array, j);  

  77.                                         if (ObjectInspectorUtils.compare(tmp, arrayElementOI, listElement,  

  78.                                                         arrayElementOI) == 0) {  

  79.                                                 break;  

  80.                                         }  

  81.                                 }  

  82.                         }  

  83.                         if(-1 == j)  

  84.                         {  

  85.                                 num++;  

  86.                         }  

  87.                 }  

  88.   

  89.                 result.set(num);  

  90.                 return result;  

  91.         }  

  92.   

  93.         public String getDisplayString(String[] children) {  

  94.                 assert (children.length == ARG_COUNT);  

  95.                 return "array_uniq_element_number(" + children[ARRAY_IDX]+ ")";  

  96.         }  

  97. }  


生成udf.jar

hive有三种方法使用自定义的UDF函数
1. 临时添加UDF

如下:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

  1. hive> select * from test;     

  2. OK  

  3. Hello  

  4. wORLD  

  5. ZXM  

  6. ljz  

  7. Time taken: 13.76 seconds  

  8. hive> add jar /home/work/udf.jar;                                

  9. Added /home/work/udf.jar to class path  

  10. Added resource: /home/work/udf.jar  

  11. hive> create temporary function mytest as 'test.udf.ToLowerCase';  

  12. OK  

  13. Time taken: 0.103 seconds  

  14. hive> show functions;  

  15. ......  

  16. mytest  

  17. ......  

  18. hive> select mytest(test.name) from test;  

  19. ......  

  20. OK  

  21. hello  

  22. world  

  23. zxm  

  24. ljz  

  25. Time taken: 38.218 seconds  

这种方式在会话结束后,函数自动销毁,因此每次打开新的会话,都需要重新add jar并且create temporary function

2. 进入会话前自动创建
使用hive -i参数在进入hive时自动初始化

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

  1. $ cat hive_init   

  2. add jar /home/work/udf.jar;  

  3. create temporary function mytest as 'test.udf.ToLowerCase';  

  4. $ hive -i hive_init   

  5. Logging initialized using configuration in file:/home/work/hive/hive-0.8.1/conf/hive-log4j.properties  

  6. Hive history file=/tmp/work/hive_job_log_work_201209200147_1951517527.txt  

  7. hive> show functions;  

  8. ......  

  9. mytest  

  10. ......  

  11. hive> select mytest(test.name) from test;  

  12. ......  

  13. OK  

  14. hello  

  15. world  

  16. zxm  

  17. ljz  

方法2和方法1本质上是相同的,区别在于方法2在会话初始化时自动完成

3. 自定义UDF注册为hive内置函数
可参考:hive利器 自定义UDF+重编译hive

和前两者相比,第三种方式直接将用户的自定义函数作为注册为内置函数,未来使用起来非常简单,但这种方式也非常危险,一旦出错,将是灾难性的,因此,建议如果不是特别通用,并且固化下来的函数,还是使用前两种方式比较靠谱。











本文转自 yntmdr 51CTO博客,原文链接:http://blog.51cto.com/yntmdr/1716940,如需转载请自行联系原作者
目录
相关文章
|
7月前
|
SQL 存储 Java
Hive UDF UDTF UDAF 自定义函数详解
Hive UDF UDTF UDAF 自定义函数详解
130 2
Hive UDF UDTF UDAF 自定义函数详解
|
3月前
|
SQL JavaScript 前端开发
用Java来开发Hive应用
用Java来开发Hive应用
38 7
|
3月前
|
SQL JavaScript 前端开发
用Java、Python来开发Hive应用
用Java、Python来开发Hive应用
34 6
|
7月前
|
SQL 缓存 Java
Hive 之 UDF 运用(包会的)
Hive的UDF允许用户自定义数据处理函数,扩展其功能。`reflect()`函数通过Java反射调用JDK中的方法,如静态或实例方法。例如,调用`MathUtils.addNumbers()`进行加法运算。要创建自定义UDF,可以继承`GenericUDF`,实现`initialize`、`evaluate`和`getDisplayString`方法。在`initialize`中检查参数类型,在`evaluate`中执行业务逻辑。最后,打包项目成JAR,上传到HDFS,并在Hive中注册以供使用。
181 2
|
7月前
|
SQL Java 程序员
Hive反射函数的使用-程序员是怎么学UDF函数的
Hive反射函数的使用-程序员是怎么学UDF函数的
43 0
|
7月前
|
SQL Java 数据处理
【Hive】Hive的函数:UDF、UDAF、UDTF的区别?
【4月更文挑战第17天】【Hive】Hive的函数:UDF、UDAF、UDTF的区别?
|
7月前
|
SQL 消息中间件 Apache
Flink报错问题之使用hive udf函数报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
|
7月前
|
SQL 分布式计算 Java
Hive自定义函数UDF编写
Hive自定义函数UDF编写
87 2
|
7月前
|
SQL 搜索推荐 Java
Hive中的UDF是什么?请解释其作用和使用方法。
Hive中的UDF是什么?请解释其作用和使用方法。
93 0
|
7月前
|
存储 SQL JSON
大数据开发岗大厂面试30天冲刺 - 日积月累,每日五题【Day02】——Hive2
大数据开发岗大厂面试30天冲刺 - 日积月累,每日五题【Day02】——Hive2
59 0