博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hive udf开发超详细手把手教程(有些过时了)
阅读量:4299 次
发布时间:2019-05-27

本文共 9199 字,大约阅读时间需要 30 分钟。

mvn install 直接打包

maven打包

上面代码测试通过以后,然后用maven打成jar包。如果是老司机,自然知道怎么做。如果是新司机,我偷偷告诉大家,eclipse里在项目上右击,选择 run as,然后maven install,maven就开始帮你打包了。如果是第一次,maven还会帮你把依赖的jar下载到本地仓库。打包完了以后,你就可以看到target目录下面出现了一个jar包,festival-1.0.jar。OK,这就是我们需要的jar包。
--------------------- 
作者:bitcarmanlee 
来源:CSDN 
原文:https://blog.csdn.net/bitcarmanlee/article/details/51249260 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

hive udf开发超详细手把手教程

2016年04月26日 11:46:34  阅读数:29652 标签:  更多

个人分类: 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bitcarmanlee/article/details/51249260

关于hive的udf介绍,就不多啰嗦了。网上的教程一抓一大把,也可以上apache的官网去查阅相关资料,我就省了翻译的时间了。重点给大家带来干货,手把手教会你怎样开发一个udf函数,已经如何部署到服务器上的hive环境中运行。用最简单的话来说,就是教大家怎么让自己开发的udf跑起来。。。

项目需求

做数据挖掘项目中,常见的需求之一就是分析节假日订单跟平时订单的区别。于是,我们需要统计节假日订单的分布情况。但是hive中显然没有内置,也不可能内置此函数,因为每年的节假日都是变得嘛。于是,我们就需要自己开发一个udf来满足需求了。

配置文件

考虑到每年的节假日其实并不多,也就那么二十多天,于是采用配置文件的方式,直接将节假日写死在配置文件中。如果需要添加,改配置文件就行。毕竟一年也就这么二十多天,工作量并不大。。。 

自己写的配置文件如下:

20140101=元旦20140131=春节20140201=春节20140202=春节20140203=春节20140204=春节20140205=春节20140206=春节20140405=清明节20140406=清明节20140407=清明节20140501=五一劳动节20140502=五一劳动节20140503=五一劳动节20140531=端午节20140601=端午节20140602=端午节20140906=中秋节20140907=中秋节20140908=中秋节20141001=国庆节20141002=国庆节20141003=国庆节20141004=国庆节20141005=国庆节20141006=国庆节20141007=国庆节20150101=元旦20150102=元旦20150103=元旦20150218=春节20150219=春节20150220=春节20150221=春节20150222=春节20150223=春节20150224=春节20150404=清明节20150405=清明节20150406=清明节20150501=五一劳动节20150502=五一劳动节20150503=五一劳动节20150620=端午节20150621=端午节20150622=端午节20150926=中秋节20150927=中秋节20151001=国庆节20151002=国庆节20151003=国庆节20151004=国庆节20151005=国庆节20151006=国庆节20151007=国庆节20160101=元旦20160102=元旦20160103=元旦20160207=春节20160208=春节20160209=春节20160210=春节20160211=春节20160212=春节20160213=春节20160402=清明节20160403=清明节20160404=清明节20160430=五一劳动节20160501=五一劳动节20160502=五一劳动节20160609=端午节20160610=端午节20160611=端午节20160915=中秋节20160916=中秋节20160917=中秋节20161001=国庆节20161002=国庆节20161003=国庆节20161004=国庆节20161005=国庆节20161006=国庆节20161007=国庆节
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

以上包含有2014,2015,2016三年的假期。如果想增加,继续往此文件里添加就是。。。

新建maven项目

现在的java项目必须是用maven管理,方便又实用,谁用谁知道,不多解释。maven项目自然只需要知道pom.xml即可。pom文件如下:

4.0.0
udf.leilei.elong.com
festival
1.0
hive
http://maven.apache.org
UTF-8
org.apache.hive
hive-exec
0.13.0
org.apache.hadoop
hadoop-common
2.5.0
org.apache.maven.plugins
maven-shade-plugin
2.2
package
shade
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

提醒对maven不是很熟的同学们:因为我们项目里有依赖的jar包,所以必须加上 maven-shade-plugin 插件。当然你用 maven-assembly-plugin 也是没有问题的。如果你对maven不是那么熟悉,别管了,先粘过去,跑起来再说吧。。。

UDF具体代码开发

package festival;import java.io.InputStreamReader;import java.text.NumberFormat;import java.util.HashMap;import java.util.Properties;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.hadoop.hive.ql.exec.UDF;public class FestivalType extends UDF{    private HashMap
festivalMap = new HashMap
(); public FestivalType() throws Exception { InputStreamReader propFile = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("festival_date.properties"), "UTF-8"); Properties prop = new Properties(); prop.load(propFile); for(Object key:prop.keySet()) { festivalMap.put(key.toString(), prop.getProperty(key.toString())); } } //解决double转string的科学计数法的问题 public String double_to_string(double dou) { Double dou_obj = new Double(dou); NumberFormat nf = NumberFormat.getInstance(); nf.setGroupingUsed(false); String dou_str = nf.format(dou_obj); return dou_str; } public String evaluate(double date_dou) { String date_str = this.double_to_string(date_dou); return evaluate(date_str); } public int evaluate(double date_dou,String flag) { String date_str = this.double_to_string(date_dou); return evaluate(date_str,flag); } public String evaluate(String date_str) { if (! this.match_date(date_str).equals("null")) { date_str = this.match_date(date_str); return festivalMap.get(date_str) == null ? "null" : festivalMap.get(date_str); } else { return "null"; } } public int evaluate(String date_str, String flag) { if (flag.equals("count") && ! this.match_date(date_str).equals("null")) { date_str = this.match_date(date_str); return festivalMap.get(date_str) == null ? 0 :1; } else { return 0; } } public String match_date(String date_str) { //匹配20160101这种日期格式 Pattern pat_common = Pattern.compile("\\d{8}"); Matcher mat_common = pat_common.matcher(date_str); //匹配2016-01-01这种日期格式 Pattern pat_strike = Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); Matcher mat_strike = pat_strike.matcher(date_str); //匹配 2016-01-01 10:35:46 这种日期格式 Pattern pat_colon = Pattern.compile("\\d{4}-\\d{2}-\\d{2}(\\s)+\\d{2}:\\d{2}:\\d{2}"); Matcher mat_colon = pat_colon.matcher(date_str); if (mat_colon.find()) { return date_str.replace("-", "").substring(0, 8); } else if(mat_strike.find()) { return date_str.replace("-", ""); } else if (mat_common.find()) { return date_str; } else { return "null"; } } //测试的main方法 public static void main(String[] args) throws Exception{ FestivalType fes = new FestivalType(); String date_str = "20150101"; System.out.println(fes.evaluate(date_str)); String date_str1 = "20160101"; String result = fes.evaluate(date_str1); System.out.println("result is:" + result); double date_dou = 20160101; int result_dou = fes.evaluate(date_dou,"count"); System.out.println(result_dou); System.out.println(date_dou); }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102

将之前的配置文件放在src/main/resources下面,然后运行此代码,输出如下:

节日类型是:元旦节日天数:1
  • 1
  • 2

因为我们这篇文章的目的是让udf以最快的速度跑起来,所以udf具体实现细节以及原理就不多写了。大家记住下面一句话就可以:继承UDF类,重写evaluate方法,就可以了。

maven打包

上面代码测试通过以后,然后用maven打成jar包。如果是老司机,自然知道怎么做。如果是新司机,我偷偷告诉大家,eclipse里在项目上右击,选择 run as,然后maven install,maven就开始帮你打包了。如果是第一次,maven还会帮你把依赖的jar下载到本地仓库。打包完了以后,你就可以看到target目录下面出现了一个jar包,festival-1.0.jar。OK,这就是我们需要的jar包。

将jar包上传

接下来,我们将前面的jar包上传到服务器上的任何一个位置。比如我就是用scp命令,不多说。

使用udf查询

#!/bin/bashhive -e "add jar /home/xxx/lei.wang/festival-1.0.jar;         create temporary function festival as 'festival.FestivalType';         set mapred.reduce.tasks = 10;         select cast(a.create_date_wid as int) create_date_wid,sum(a.festival_order_num) from            (select create_date_wid,festival(create_date_wid,'count') as festival_order_num from ora_dw_rewrite.olap_b_dw_hotelorder_f                where create_date_wid>=20160101 and create_date_wid<=20160406)a            where a.festival_order_num > 0                group by a.create_date_wid                    order by create_date_wid;"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

为了达到快速上手的目的,直接上代码。

add jar /home/xxx/lei.wang/festival-1.0.jar;
  • 1

这一行是将jar包加进来,后面是你前面上传的路径地址

create temporary function festival as 'festival.FestivalType';
  • 1

创建一个临时函数,用来查询,festival.FestivalType是package名+类名,无需多解释。 

后面的查询语句,也不多解释了。有点sql基础的同学,应该都能看明白。

最后查询结果

..........Stage-Stage-1: Map: 62  Reduce: 10   Cumulative CPU: 1547.44 sec   HDFS Read: 29040366442 HDFS Write: 1298 SUCCESSStage-Stage-2: Map: 8  Reduce: 1   Cumulative CPU: 23.88 sec   HDFS Read: 4608 HDFS Write: 205 SUCCESSTotal MapReduce CPU Time Spent: 26 minutes 11 seconds 320 msecOK20160101    xxx20160102    xxx20160103    xxx20160207    xxx20160208    xxx20160209    xxx20160210    xxx20160211    xxx20160212    xxx20160213    xxx20160402    xxx20160403    xxx20160404    xxxTime taken: 159.805 seconds, Fetched: 13 row(s)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

后面的具体数值是公司机密,不能透露,嘻嘻。 

稍微注意一点是cast(a.create_date_wid as int),这里因为create_date_wid存的是double类型,如果不做转化的话,会显示成科学计数法,2.0150326E7这种形式。所以为了好看一些,将其强转成int类型。 
还有就是这种add的方式的有效期是session级别,就是在此seession有效,session关闭以后就无效。所以如果要将其固话的话,可以加到hive的classpath里头。这样hive启动的时候,就将其加到classpath里了,无需再手动add jar。

结束语

至此,一个完整的hive udf开发过程就结束了。当然还可以开发UDAF,限于时间有限,就不再详细介绍。欢迎有搞数据,算法的志同道合的同学们一起研究讨论

QQ:535352700 

EMAIL:bit_carmanlee@sina.com

你可能感兴趣的文章
Python打印二叉树的左视图、右视图
查看>>
OpenStack Mitaka Horizon 主题开发
查看>>
OpenStack Mitaka keystone 分页(pagination)实现
查看>>
OpenStack删除Cinder盘失败解决办法
查看>>
Linux cpu 详解
查看>>
GitHub + Hexo 搭建个人博客
查看>>
Linux Ubuntu 修改网卡名字
查看>>
OpenStack Ocata Horizon 开发(一)—— 快速开始
查看>>
自定义Horizon
查看>>
Django 源码阅读:服务启动(wsgi)
查看>>
Django 源码阅读:url解析
查看>>
第三轮面试题
查看>>
Docker面试题(一)
查看>>
第四轮面试题
查看>>
第一轮面试题
查看>>
2020-11-18
查看>>
Docker面试题(二)
查看>>
一、redis面试题及答案
查看>>
消息队列2
查看>>
消息列队3
查看>>