Hive UDF开发指南
编写Apache Hive用户自定义函数(UDF)有两个不同的接口,一个非常简单,另一个...就相对复杂点。
复杂API: org.apache.hadoop.hive.ql.udf.generic.GenericUDF
如果你想浏览代码:fork it on Github:https://github.com/rathboma/hive-extension-examples
简单API
- class SimpleUDFExample extends UDF {
- public Text evaluate(Text input) {
- return new Text("Hello " + input.toString());
- }
- }
因为该UDF是一个简单的函数,你可以在规范的测试工具测试它,如JUnit。
- public class SimpleUDFExampleTest {
- @Test
- public void testUDF() {
- SimpleUDFExample example = new SimpleUDFExample();
- Assert.assertEquals("Hello world", example.evaluate(new Text("world")).toString());
- }
- }
好的,在Hive控制台测试一把,也可以在hive中直接测试这个UDF,特别是当你不完全肯定该函数是否能够正确处理问题的时候
- %> hive
- hive> ADD JAR target/hive-extensions-1.0-SNAPSHOT-jar-with-dependencies.jar;
- hive> CREATE TEMPORARY FUNCTION helloworld as 'com.matthewrathbone.example.SimpleUDFExample';
- hive> select helloworld(name) from people limit 1000;
事实上,上述UDF有一个bug,不会去检查null参数,null在一个大的数据集当中是很常见的,所以要适当严谨点。作为回应,这边在函数中加了一个null检查
- class SimpleUDFExample extends UDF {
- public Text evaluate(Text input) {
- if(input == null) return null;
- return new Text("Hello " + input.toString());
- }
- }
然后加了一个测试去验证它
- @Test
- public void testUDFNullCheck() {
- SimpleUDFExample example = new SimpleUDFExample();
- Assert.assertNull(example.evaluate(null));
- }
用mvn test跑一下测试,来保证所有用例通过。
复杂的API
- // 这个类似于简单API的evaluat方法,它可以读取输入数据和返回结果
- abstract Object evaluate(GenericUDF.DeferredObject[] arguments);
- // 该方法无关紧要,我们可以返回任何东西,但应当是描述该方法的字符串
- abstract String getDisplayString(String[] children);
- // 只调用一次,在任何evaluate()调用之前,你可以接收到一个可以表示函数输入参数类型的object inspectors数组
- // 这是你用来验证该函数是否接收正确的参数类型和参数个数的地方
- abstract ObjectInspector initialize(ObjectInspector[] arguments);
可能要通过一个示例才能去了解这个接口,所以接下来往下看。
示例
一个String的列表(list)
一个String
- containsString(List("a", "b", "c"), "b"); // true
- containsString(List("a", "b", "c"), "d"); // false
不同于UDF接口,这个GenericUDF接口需要更啰嗦点。
- class ComplexUDFExample extends GenericUDF {
- ListObjectInspector listOI;
- StringObjectInspector elementOI;
- @Override
- public String getDisplayString(String[] arg0) {
- return "arrayContainsExample()"; // this should probably be better
- }
- @Override
- public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
- if (arguments.length != 2) {
- throw new UDFArgumentLengthException("arrayContainsExample only takes 2 arguments: List<T>, T");
- }
- // 1. 检查是否接收到正确的参数类型
- ObjectInspector a = arguments[0];
- ObjectInspector b = arguments[1];
- if (!(a instanceof ListObjectInspector) || !(b instanceof StringObjectInspector)) {
- throw new UDFArgumentException("first argument must be a list / array, second argument must be a string");
- }
- this.listOI = (ListObjectInspector) a;
- this.elementOI = (StringObjectInspector) b;
- // 2. 检查list是否包含的元素都是string
- if(!(listOI.getListElementObjectInspector() instanceof StringObjectInspector)) {
- throw new UDFArgumentException("first argument must be a list of strings");
- }
- // 返回类型是boolean,所以我们提供了正确的object inspector
- return PrimitiveObjectInspectorFactory.javaBooleanObjectInspector;
- }
- @Override
- public Object evaluate(DeferredObject[] arguments) throws HiveException {
- // 利用object inspectors从传递的对象中得到list与string
- List<String> list = (List<String>) this.listOI.getList(arguments[0].get());
- String arg = elementOI.getPrimitiveJavaObject(arguments[1].get());
- // 检查空值
- if (list == null || arg == null) {
- return null;
- }
- // 判断是否list中包含目标值
- for(String s: list) {
- if (arg.equals(s)) return new Boolean(true);
- }
- return new Boolean(false);
- }
- }
代码走读
1、该UDF用默认的构造器来初始化
1) 检查传人的参数有两个与该参数的数据类型是正确的(见上面)
2) 我们保存object instructors用以供evaluate()使用(listOI, elementOI)
3) 返回 object inspector,让Hive能够读取该函数的返回结果(BooleanObjectInspector)
1) 我们利用initialize方法中存储的object instructors来抽取出正确的值。
2) 我们在这处理我们的逻辑然后用initialize返回的object inspector来序列化返回来的值(list.contains(elemement) ? true : false)。
测试
测试该函数比较复杂的部分是初始化,一旦调用顺序明确了,我们就知道怎么去构建该对象测试流程,非常简单。
- public class ComplexUDFExampleTest {
- @Test
- public void testComplexUDFReturnsCorrectValues() throws HiveException {
- // 建立需要的模型
- ComplexUDFExample example = new ComplexUDFExample();
- ObjectInspector stringOI = PrimitiveObjectInspectorFactory.javaStringObjectInspector;
- ObjectInspector listOI = ObjectInspectorFactory.getStandardListObjectInspector(stringOI);
- JavaBooleanObjectInspector resultInspector = (JavaBooleanObjectInspector) example.initialize(new ObjectInspector[]{listOI, stringOI});
- // create the actual UDF arguments
- List<String> list = new ArrayList<String>();
- list.add("a");
- list.add("b");
- list.add("c");
- // 测试结果
- // 存在的值
- Object result = example.evaluate(new DeferredObject[]{new DeferredJavaObject(list), new DeferredJavaObject("a")});
- Assert.assertEquals(true, resultInspector.get(result));
- // 不存在的值
- Object result2 = example.evaluate(new DeferredObject[]{new DeferredJavaObject(list), new DeferredJavaObject("d")});
- Assert.assertEquals(false, resultInspector.get(result2));
- // 为null的参数
- Object result3 = example.evaluate(new DeferredObject[]{new DeferredJavaObject(null), new DeferredJavaObject(null)});
- Assert.assertNull(result3);
- }
- }
结束语
虽然在这篇文章中有一些其他的东西没提及到,但是另外有UDAF函数与UDTF函数,UDAF函数能够在一个函数中处理与聚集多行数据,如果你更感兴趣,这里有一些资源可以提供帮助。
翻译来自于
Hive UDF开发指南的更多相关文章
- 最强最全面的Hive SQL开发指南,超四万字全面解析
本文整体分为两部分,第一部分是简写,如果能看懂会用,就直接从此部分查,方便快捷,如果不是很理解此SQL的用法,则查看第二部分,是详细说明,当然第二部分语句也会更全一些! 第一部分: hive模糊搜索表 ...
- Hive UDF开发-简介
Hive进行UDF开发十分简单,此处所说UDF为Temporary的function,所以需要hive版本在0.4.0以上才可以. Hive的UDF开发只需要重构UDF类的evaluate函数即可.例 ...
- Hive UDF开发 第一个例子
package udf; import org.apache.hadoop.hive.ql.exec.UDF; public class helloudf extends UDF{ public St ...
- Hive UDTF开发指南
在这篇文章中,我们将深入了解用户定义表函数(UDTF),该函数的实现是通过继承org.apache.Hadoop.hive.ql.udf.generic.GenericUDTF这个抽象通用类,UDTF ...
- Hive UDF开发实例学习
1. 本地环境配置 必须包含的一些包. http://blog.csdn.net/azhao_dn/article/details/6981115 2. 去重UDF实例 http://blog.csd ...
- hive UDF函数
虽然Hive提供了很多函数,但是有些还是难以满足我们的需求.因此Hive提供了自定义函数开发 自定义函数包括三种UDF.UADF.UDTF UDF(User-Defined-Function) ...
- Hive UDAF开发之同时计算最大值与最小值
卷首语 前一篇文章hive UDAF开发入门和运行过程详解(转)里面讲过UDAF的开发过程,其中说到如果要深入理解UDAF的执行,可以看看求平均值的UDF的源码 本人在看完源码后,也还是没能十分理解里 ...
- 2、Hive UDF编程实例
Hive的UDF包括3种:UDF(User-Defined Function).UDAF(User-Defined Aggregate Function)和UDTF(User-Defined Tabl ...
- HADOOP docker(六):hive简易使用指南
前言1.hive简介1.1 hive组件与相应功能:1.2 hive的表类型1.3 分区表1.3 分隔符1.4 hive的数据存储2.数据类型2.1 基本数据类型2.1 复杂数据类型2.3 NULL3 ...
随机推荐
- 《C#高效编程》读书笔记09-避免在API中使用转换操作符
转换操作符为类之间引入了一种"可替换性"(substitutability)."可替换性"表示一个类的实例可以替换为另一个类的实例. public class ...
- C 碎片三 运算符与表达式
一.算术运算符 算术运算符:+. -. *. /. %等 加:+ 减: - 乘: * 除: / 除数不能为0 模:% 参与模运算的数据不能为小数 二.赋值运算符 赋值运算符:= 作用: ...
- mysql 批量修改 表字段/表/数据库 字符集和排序规则
今天接到一个任务是需要把数据库的字符编码全部修改一下,写了以下修正用的SQL,修正顺序是 表字段 > 表 > 数据库. 表字段修复: #改变字段数据 SELECT TABLE_SCHE ...
- 树莓派-(一)开箱到点亮一些坑(无屏、无wlan、无直连键鼠)
0x00.前期准备: 材料: 树莓派3b+ 板子 * 1,适配电源 * 1,网线 * 2,sd卡16G * 1,读卡器 * 1 安装时注意,3b+三个散热片贴好.小风扇接线要接对 工具: 0x01. ...
- js为页面元素添加水印
近期有需求为页面部分区域添加上水印,通过在网上找到了js为页面添加水印的方法,后来经过自己的改进,可以实现为页面部分元素添加水印,最终效果如下图: 代码如下: function watermark(s ...
- PHP代码规范的一些总结
世界第一语言在手,辅以前人的最佳实践,天下又算什么. 1.代码是写给小白用的 注释,注释,注释,重要的事情说三遍.我们做的虽然不是拿去卖源码的商业产品,不需要把注释写的多么优美.但也不要太过吝啬,到头 ...
- COGS 1043. [Clover S2] Freda的迷宫
★ 输入文件:mazea.in 输出文件:mazea.out 简单对比时间限制:1 s 内存限制:128 MB Freda 的迷宫 (mazea.pas/.c/.cpp) 题目叙述 F ...
- PHP:is_string()字符串函数
is_string() is_string() - 检测变量是否是字符串. 描述:bool is_string( mixed $var ) 如果var是sring则返回TRUE,否则返回FALSE.m ...
- Java 使用正则表达式取出图片地址以及跳转的链接地址,来判断死链(一)
任务:通过driver的getPageSource()获取网页的源码内容,在把网页中图片链接地址和跳转的url地址进行过滤,在get每个请求,来判断是否是死链 如图: 获取网页源码中所有的href,以 ...
- hdu-2680 Choose the best route---dijkstra+反向存图或者建立超级源点
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2680 题目大意: 给你一个有向图,一个起点集合,一个终点,求最短路 解题思路: 1.自己多加一个超级 ...