Welcome to aparke’s blog!
通过udf自定义函数解决一些hive解决不了的问题
描述udf自定义函数
1.UDF是什么?
hive的类SQL预发给数据挖掘工作者带来了很多便利,海量数据通过简单的sql就可以完成分析,有时候hive提供的函数功能满足不了业务需要,就需要我们自己来写UDF函数来辅助完成,下面用一个简单的例子说明过程,以及注意事项。
UDF函数其实就是一个简单的函数,执行过程就是在Hive转换成mapreduce程序后,执行java方法,类似于像Mapreduce执行过程中加入一个插件,方便扩展. UDF只能实现一进一出的操作,如果需要实现多进一出,则需要实现UDAF
Hive可以允许用户编写自己定义的函数UDF,来在查询中使用。
2.UDF类型
Hive中有3种UDF:
- UDF:操作单个数据行,产生单个数据行;
- UDAF:操作多个数据行,产生一个数据行。
- UDTF:操作一个数据行,产生多个数据行一个表作为输出。
3.如何构建UDF
用户构建的UDF使用过程如下:
第一步:继承UDF或者UDAF或者UDTF,实现特定的方法。
第二步:将写好的类打包为jar。如hivefirst.jar.
第三步:进入到Hive环境中,利用add jar /home/hadoop/hivefirst.jar.注册该jar文件
第四步:为该类起一个别名,create temporary function mylength as ‘com.whut.StringLength’;这里注意UDF只是为这个Hive会话临时定义的。
第五步:在select中使用mylength();
4.自定义UDF
思路解决要点:
hive中如何定义自己的函数:
- 1、先写一个java类(extends UDF,重载方法public C evaluate(A a,B b)),实现你所想要的函数的功能(传入一个json字符串和一个脚标,返回一个值)
- 2、将java程序打成jar包,上传到hive所在的机器
- 3、在hive命令行中将jar包添加到classpath :
hive>add jar /root/hivetest/myjson.jar;
- 4、在hive命令中用命令创建一个函数叫做myjson,关联你所写的这个java类
hive> create temporary function myjson as 'cn.aparke.hive.udf.MyJsonParser';
注:临时函数只在一次hive会话中有效,重启会话后就无效
如果需要经常使用该自定义函数,可以考虑创建永久函数:
拷贝jar包到hive的类路径中:
cp myjson.jar opt/hive-1.2.1/lib/
创建了:
create function pfuncx as ‘com.doit.hive.udf.UserInfoParser’;
删除函数:
DROP TEMPORARY FUNCTION [IF EXISTS] function_name
DROP FUNCTION[IF EXISTS] function_name
场景应用
有如下json数据:rating.json{"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"}
{"movie":"661","rate":"3","timeStamp":"978302109","uid":"1"}
{"movie":"914","rate":"3","timeStamp":"978301968","uid":"1"}
{"movie":"3408","rate":"4","timeStamp":"978300275","uid":"1"}
需求:求每个人评论的次数
1.建表映射上述数据create table t_ratingjson(json string);
load data local inpath '/root/hive1/rating.json' into table t_ratingjson;
–由于数据太大之查看前10行select * from t_ratingjson limit 10;
+----------------------------------------------------------------+--+
| t_ratingjson.json |
+----------------------------------------------------------------+--+
| {"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"} |
| {"movie":"661","rate":"3","timeStamp":"978302109","uid":"1"} |
| {"movie":"914","rate":"3","timeStamp":"978301968","uid":"1"} |
| {"movie":"3408","rate":"4","timeStamp":"978300275","uid":"1"} |
| {"movie":"2355","rate":"5","timeStamp":"978824291","uid":"1"} |
| {"movie":"1197","rate":"3","timeStamp":"978302268","uid":"1"} |
| {"movie":"1287","rate":"5","timeStamp":"978302039","uid":"1"} |
| {"movie":"2804","rate":"5","timeStamp":"978300719","uid":"1"} |
| {"movie":"594","rate":"4","timeStamp":"978302268","uid":"1"} |
| {"movie":"919","rate":"4","timeStamp":"978301368","uid":"1"} |
+----------------------------------------------------------------+--+
想把上面的原始数据去掉key值变成如下形式:1193,5,978300760,1
661,3,978302109,1
914,3,978301968,1
3408,4,978300275,1
思路:定义一个json解析函数
写hive(导入lib目录下的jar到项目下 add budilpath)
函数(java代码) 打jar包 导入 加载 运行
0: jdbc:hive2://master:10000> add jar /root/hive1/hive_myjson.jar; |
创建一个临时函数关联jar包create temporary function myjson as 'cn.aparke.udf.myjson';
使用自己定义的临时函数名构造如下sql 保存结果到新表 t_rate下
create table t_rate |
最后在解析后的表中group by uid 得到每个人评论次数select uid,count(1) from t_rate group by uid,rate limit 50;
+-------+------+--+
| uid | _c1 |
+-------+------+--+
| 1 | 8 |
| 1 | 27 |
| 1 | 18 |
| 10 | 12 |
| 10 | 84 |
| 10 | 151 |
| 10 | 154 |
| 100 | 3 |
| 100 | 15 |
| 100 | 38 |
| 100 | 17 |
| 100 | 3 |
| 1000 | 2 |
| 1000 | 13 |
| 1000 | 41 |
| 1000 | 28 |
| 1001 | 6 |
| 1001 | 68 |
| 1001 | 57 |
| 1001 | 166 |
| 1001 | 80 |
| 1002 | 4 |
| 1002 | 9 |
| 1002 | 27 |
| 1002 | 26 |
| 1003 | 7 |
| 1003 | 11 |
| 1003 | 11 |
| 1004 | 37 |
| 1004 | 98 |
| 1004 | 146 |
| 1004 | 151 |
| 1004 | 49 |
| 1005 | 8 |
| 1005 | 3 |
| 1005 | 7 |
| 1005 | 24 |
| 1005 | 50 |
| 1006 | 7 |
| 1006 | 8 |
| 1006 | 10 |
| 1006 | 13 |
| 1006 | 6 |
| 1007 | 7 |
| 1007 | 11 |
| 1007 | 14 |
| 1008 | 1 |
| 1008 | 1 |
| 1008 | 12 |
| 1008 | 27 |
+-------+------+--+
内置json解析函数
一行解决select json_tuple(json,'movie','rate','timeStamp','uid') as(movie,rate,ts,uid) from t_ratingjson;
+--------+-------+------------+------+--+
| movie | rate | ts | uid |
+--------+-------+------------+------+--+
| 1193 | 5 | 978300760 | 1 |
| 661 | 3 | 978302109 | 1 |
| 914 | 3 | 978301968 | 1 |
| 3408 | 4 | 978300275 | 1 |
| 2355 | 5 | 978824291 | 1 |
| 1197 | 3 | 978302268 | 1 |
| 1287 | 5 | 978302039 | 1 |
| 2804 | 5 | 978300719 | 1 |
| 594 | 4 | 978302268 | 1 |
| 919 | 4 | 978301368 | 1 |
+--------+-------+------------+------+--+