[一起学Hive]之十八-Hive UDF开发

来源:互联网 发布:交大知行大厦 邮编 编辑:程序博客网 时间:2024/05/22 04:43

Hive中,除了提供丰富的内置函数(见[一起学Hive]之二–Hive函数大全-完整版)之外,还允许用户使用Java开发自定义的UDF函数。

开发自定义UDF函数有两种方式,一个是继承org.apache.hadoop.hive.ql.exec.UDF,另一个是继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF;

如果是针对简单的数据类型(比如String、Integer等)可以使用UDF,如果是针对复杂的数据类型(比如Array、Map、Struct等),可以使用GenericUDF,另外,GenericUDF还可以在函数开始之前和结束之后做一些初始化和关闭的处理操作。

UDF

使用UDF非常简单,只需要继承org.apache.hadoop.hive.ql.exec.UDF,并定义

public Object evaluate(Object args) {} 方法即可。

比如,下面的UDF函数实现了对一个String类型的字符串取HashMD5:

  1. package com.lxw1234.hive.udf;
  2.  
  3. import org.apache.hadoop.hbase.util.Bytes;
  4. import org.apache.hadoop.hbase.util.MD5Hash;
  5. import org.apache.hadoop.hive.ql.exec.UDF;
  6.  
  7. public class HashMd5 extends UDF {
  8. public String evaluate(String cookie) {
  9. return MD5Hash.getMD5AsHex(Bytes.toBytes(cookie));
  10. }
  11. }
  12.  

将上面的HashMd5类打成jar包,udf.jar

使用时候,在Hive命令行执行:

  1. add jar file:///tmp/udf.jar;
  2. CREATE temporary function str_md5 as 'com.lxw1234.hive.udf.HashMd5';
  3. select str_md5(‘lxw1234.com’) from dual;

GenericUDF

继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF之后,需要重写几个重要的方法:

public void configure(MapredContext context) {}

//可选,该方法中可以通过context.getJobConf()获取job执行时候的Configuration;

//可以通过Configuration传递参数值

public ObjectInspector initialize(ObjectInspector[] arguments)

//必选,该方法用于函数初始化操作,并定义函数的返回值类型;

//比如,在该方法中可以初始化对象实例,初始化数据库链接,初始化读取文件等;

public Object evaluate(DeferredObject[] args){}

//必选,函数处理的核心方法,用途和UDF中的evaluate一样;

public String getDisplayString(String[] children)

//必选,显示函数的帮助信息

public void close(){}

//可选,map完成后,执行关闭操作

 

下面的程序将一个以逗号分隔的字符串,切分成List,并返回:

  1. package com.lxw1234.hive.udf;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Date;
  5.  
  6. import org.apache.hadoop.hive.ql.exec.MapredContext;
  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.GenericUDF;
  10. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
  11. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
  12. import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
  13. import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
  14.  
  15. /**
  16. * http://lxw1234.com
  17. * lxw的大数据田地
  18. * @author lxw1234
  19. * 该函数用于将字符串切分成List,并返回
  20. */
  21. public class Lxw1234GenericUDF extends GenericUDF {
  22. private static int mapTasks = 0;
  23. private static String init = "";
  24. private transient ArrayList ret = new ArrayList();
  25. @Override
  26. public void configure(MapredContext context) {
  27. System.out.println(new Date() + "######## configure");
  28. if(null != context) {
  29. //从jobConf中获取map数
  30. mapTasks = context.getJobConf().getNumMapTasks();
  31. }
  32. System.out.println(new Date() + "######## mapTasks [" + mapTasks + "] ..");
  33. }
  34. @Override
  35. public ObjectInspector initialize(ObjectInspector[] arguments)
  36. throws UDFArgumentException {
  37. System.out.println(new Date() + "######## initialize");
  38. //初始化文件系统,可以在这里初始化读取文件等
  39. init = "init";
  40. //定义函数的返回类型为java的List
  41. ObjectInspector returnOI = PrimitiveObjectInspectorFactory
  42. .getPrimitiveJavaObjectInspector(PrimitiveObjectInspector.PrimitiveCategory.STRING);
  43. return ObjectInspectorFactory.getStandardListObjectInspector(returnOI);
  44. }
  45.  
  46. @Override
  47. public Object evaluate(DeferredObject[] args) throws HiveException {
  48. ret.clear();
  49. if(args.length < 1) return ret;
  50. //获取第一个参数
  51. String str = args[0].get().toString();
  52. String[] s = str.split(",",-1);
  53. for(String word : s) {
  54. ret.add(word);
  55. }
  56. return ret;
  57. }
  58.  
  59. @Override
  60. public String getDisplayString(String[] children) {
  61. return "Usage: Lxw1234GenericUDF(String str)";
  62. }
  63.  
  64. }
  65.  

其中,在configure方法中,获取了本次任务的Map Task数目;

在initialize方法中,初始化了一个变量init,并定义了返回类型为java的List类型;

getDisplayString方法中显示函数的用法;

evaluate是核心的逻辑处理;

 

需要特别注意的是,configure方法,“This is only called in runtime of MapRedTask”,该方法只有在运行map task时候才被执行。它和initialize用法不一样,如果在initialize时候去使用MapredContext,则会报Null,因为此时MapredContext还是Null。

 

上面的函数执行后,在MapReduce的日志中打印出了以下内容:

hive udf

即在MapReduce阶段,GenericUDF几个方法的执行顺序为:

configure–>initialize–>evaluate–>close

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 梦幻西游新区抢不到副本积分怎么办 倒车时遇上机动车碰瓷的怎么办 电瓶车相撞对方全责但不赔偿怎么办 轻微刮蹭逃逸对方想多要钱怎么办 正常开车撞伤了闯红灯的人怎么办 发现小事故要保持现场堵车怎么办 私处刮毛外面皮肤不小心弄伤怎么办 老婆骂孩子不准老公带饿小孩怎么办 结婚3年妻子不让丈夫碰怎么办 老婆出轨现在没证据他要离婚怎么办 结婚后老婆不让碰分房睡离婚怎么办 电动车调速把手变速挡坏了怎么办 路边车辆贴条了超过15天了怎么办 违停交警拍照了没贴条 照片怎么办 支付宝违章缴费罚单输错了怎么办 交警查酒驾跑了把警车撞了怎么办 禁止进入待行区的时候进入了怎么办 今天开车把72岁老太婆撞了怎么办 在这种路口遇到行人突然横穿怎么办 在左拐车道却直行了怎么办 路边简易房让拆除不想拆怎么办 英国护照的名和姓印颠倒了怎么办 加热圈功率小加不到设定温度怎么办 本田飞度05年车尾气不好怎么办 文件在lr中打开后找不到了怎么办 手机安装软件成功屏幕上没有怎么办 脸过敏发红痒怎么办用什么药膏 脸上又红又肿又痒怎么办 宝宝把皮革咬烂吃掉了怎么办 自动档皮革挡把防尘套烂了怎么办 pu包用酒精擦坏了怎么办 白色的面料被84弄黄了怎么办 要账的人赖在家不走怎么办 两塔吊的安全距离不够2米怎么办 腿上被蚊子咬后留下的黑疤怎么办 携程订的酒店酒店一直没确认怎么办 客斤的无窗挨着厨房怎么办 餐桌和墙紧挨着容易脏怎么办 vivo手机被设置成英文该怎么办 电脑开机后显示英文字该怎么办? 看到文言文就不会翻译该怎么办呢