Hive开发UDF

xiaoxiao2021-02-28  82

Hive开发UDF

从无到有开发hive的udf,本篇不针对简单的,针对复杂参数

 移除点击此处添加图片说明文字

目录:

add jar /opt/workspace/udf/GetAppUDF.jar;

  移除点击此处添加图片说明文字

小坑,路径一定要写对,之前出现文件找不到,我以为要放到hdfs上面呢。

[hive@dw-gateway03 root]$ hadoop fs -mkdir /user/hive/warehouse/udf

[hive@dw-gateway03 root]$ hadoop fs -put /opt/workspace/udf​/GetAppUDF-1.0.jar /user/hive/warehouse/udf/GetAppUDF.jar​

后来及时悬崖勒马。

创建临时函数:

create temporary function GetAppUDF as 'com.test.Hive.udf.GetAppUDF';

  移除点击此处添加图片说明文字

​哦,原来是jdk版本有问题啊。

  移除点击此处添加图片说明文字

​本机是最新版,看下服务器的,

  移除点击此处添加图片说明文字

​嗯,1.7.0_55的,咱们要去安装一下了。

  移除点击此处添加图片说明文字

安装

  移除点击此处添加图片说明文字

​等一下进度

  移除点击此处添加图片说明文字

  移除点击此处添加图片说明文字

  移除点击此处添加图片说明文字

​然后咱们remove换一下jdk

搞定之后,重新打包吧。

然后发布,还是这个玩意:

  移除点击此处添加图片说明文字

​好难受呀。

然后咱们换第三个,1.7.0.88次修改,第三次装jdk好了,报另一个错了。

解决了这个问题了,还是蛮开心的。

  移除点击此处添加图片说明文字

​咱们再:

create temporary function GetAppUDF as 'com.test.Hive.udf.GetAppUDF'; 

create temporary function GetAppUDF  as ' com.test.Hive.udf.GetAppUDF '; 

总是报错:FAILED: Class com.test.Hive.udf.GetAppUDF not found

后来我发现了,乱倒腾发现的。

  移除点击此处添加图片说明文字

​那我们把他重新打印一遍:

add jar /opt/workspace/udf/GetAppUDF.jar;

create temporary function GetAppUDF  as 'com.test.Hive.udf.GetAppUDF'; 

然后我们运行

  移除点击此处添加图片说明文字

​我靠,然后我desc safedata.apk_use

发现

  移除点击此处添加图片说明文字

​array<struct<apk:string,n:string,v:string,v_n:string,c:int,t:int>>

这种格式的字段,我第一次见到。

然后咱们查资料发现这么个东西:

  移除点击此处添加图片说明文字

​暂且理解为全部强制性读进来。

但是这回报错:

  移除点击此处添加图片说明文字

​这个到底是怎么回事呢?

原来是因为我们复制了很多>

  移除点击此处添加图片说明文字

​那好,我们把>删掉,重来。

select  uuid,GetAppUDF(apk_use),pt from safedata.apk_use limit 100;

结果:

FAILED: SemanticException [Error 10014]: Line 3:1 Wrong arguments 'apk_use': No matching method for class com.test.Hive.udf.GetAppUDF with (array<struct<apk:string,n:string,v:string,v_n:string,c:int,t:int>>). Possible choices: _FUNC_(string)  

原因就是这个格式,很恶心, array<struct<apk:string,n:string,v:string,v_n:string,c:int,t:int>>

卡了很久,怎么办呢。

卡住了很久,我感觉要来个狠得。请看

  移除点击此处添加图片说明文字

​结果气得想吐学:

  移除点击此处添加图片说明文字

​java也这么蠢啊,好难受,妈的。

去网上找大神操作吧。

  移除点击此处添加图片说明文字

​还是老样子,卡在这里快一到两个小时了,问了一下老大,他也不知道,让我研究。那好吧,继续研究吧。

我们看一篇文章:

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:

package com.lxw1234.hive.udf; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.MD5Hash; import org.apache.hadoop.hive.ql.exec.UDF; public class HashMd5 extends UDF { public String evaluate(String cookie) { return MD5Hash.getMD5AsHex(Bytes.toBytes(cookie)); } }

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

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

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

具体文章我粘贴一下地址:

http://www.cnblogs.com/1130136248wlxk/articles/5519276.html

GenericUDF

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

publicvoid 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完成后,执行关闭操作

所以我们新写一个类吧。

  移除点击此处添加图片说明文字

​然后我们改写之后,出现:

  移除点击此处添加图片说明文字

add jar /opt/workspace/udf/GetAppUDF.jar;

create temporary function GetAppUDF  as 'com.test.Hive.udf.GetAppUDF2'; 

select  uuid,GetAppUDF(apk_use),pt from safedata.apk_use limit 100; 

但是,我们看到还是这个问题啊、

Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/json/JSONArray

那接下来该怎么办,只能重新想办法了。

后来我想到了一个好的点子,卡了一整个下午,我就在向着怎么会找不到json类,一个原因是真的转不了,还有一个可能就是,根本没有接收到参数,所以空,也会报这个错。那么我换个巧妙地方式,你不是要微博的数据吗。那我这样。

  移除点击此处添加图片说明文字

​可以,很巧妙,发布试一下:

  移除点击此处添加图片说明文字

那我们把object换成String把。重新发布。​

但是:Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassCastException: java.lang.String cannot be cast to [Ljava.lang.Object;

这个其实就是转换错误的,我们看看程序吧。

我靠你大爷的,改了好久好久我的天:

  移除点击此处添加图片说明文字

卡了太久了。受不了了。然后我思考了很久,发现了这个代码

  移除点击此处添加图片说明文字

​细心的发现了这个是list,我靠,坑啊,血坑。

//return ObjectInspectorFactory.getStandardListObjectInspector(returnOI);

return returnOI;

  移除点击此处添加图片说明文字

​给力了。我的哥。

好了,接下来开发。

add jar /opt/workspace/udf/GetAppUDF.jar;

create temporary function GetAppUDF  as 'com.test.Hive.udf.GetAppUDF2'; 

drop table testing.testweiboudf;

create table testing.testWeiboUDF as select im,is,uuid,GetAppUDF(apk_list) ifWeibo,dt,pt from safedata.apk_list where apk_list is not null;

  移除点击此处添加图片说明文字

​好像有不少任务,

  移除点击此处添加图片说明文字

​等到hive转化的mapreduce跑完了,就可以了。

  移除点击此处添加图片说明文字

​然后我们发现全量表切割后,字段全部为false。

那简单,我们换一个应用试一试,换唯品会吧,或者是别的什么的。

  移除点击此处添加图片说明文字

​如果换成“微博”还不行,要么就是utf-8的事情,要么,就真的没有微博,接下来就换别的试试了,没有办法了。只能如此。等等跑完了看看吧,这个udf有点恶心。

  移除点击此处添加图片说明文字

这就很尴尬了,我们换一个。看看到底怎么回事。然后我试了一试别的,发现怎么都是false,这就有问题了。

这个中间报了个这么错:

  移除点击此处添加图片说明文字

​因为是那种特殊数组格式,我们得加一个is not null

改好了之后,还是这样,算了,先告一段落吧,下午要开发python爬虫了,没时间搞这个了,先停一段落吧。等这周后期,咱们再整这个吧,现在就差一点点了。后面如果有时间我们再把这个array<struct<>>解析一下吧。

其实简单的udf很好写,就是重写一个 evaluate函数,然后用参数取得字段值,分解,复杂的这个,继承GenericUDF,重写三个方法,initialize、evaluate、getdisplayString

  移除点击此处添加图片说明文字

目录:

add jar /opt/workspace/udf/GetAppUDF.jar;

  移除点击此处添加图片说明文字

小坑,路径一定要写对,之前出现文件找不到,我以为要放到hdfs上面呢。

[hive@dw-gateway03 root]$ hadoop fs -mkdir /user/hive/warehouse/udf

[hive@dw-gateway03 root]$ hadoop fs -put /opt/workspace/udf​/GetAppUDF-1.0.jar /user/hive/warehouse/udf/GetAppUDF.jar​

后来及时悬崖勒马。

创建临时函数:

create temporary function GetAppUDF as 'com.test.Hive.udf.GetAppUDF';

  移除点击此处添加图片说明文字

​哦,原来是jdk版本有问题啊。

  移除点击此处添加图片说明文字

​本机是最新版,看下服务器的,

  移除点击此处添加图片说明文字

​嗯,1.7.0_55的,咱们要去安装一下了。

  移除点击此处添加图片说明文字

安装

  移除点击此处添加图片说明文字

​等一下进度

  移除点击此处添加图片说明文字

  移除点击此处添加图片说明文字

  移除点击此处添加图片说明文字

​然后咱们remove换一下jdk

搞定之后,重新打包吧。

然后发布,还是这个玩意:

  移除点击此处添加图片说明文字

​好难受呀。

然后咱们换第三个,1.7.0.88次修改,第三次装jdk好了,报另一个错了。

解决了这个问题了,还是蛮开心的。

  移除点击此处添加图片说明文字

​咱们再:

create temporary function GetAppUDF as 'com.test.Hive.udf.GetAppUDF'; 

create temporary function GetAppUDF  as ' com.test.Hive.udf.GetAppUDF '; 

总是报错:FAILED: Class com.test.Hive.udf.GetAppUDF not found

后来我发现了,乱倒腾发现的。

  移除点击此处添加图片说明文字

​那我们把他重新打印一遍:

add jar /opt/workspace/udf/GetAppUDF.jar;

create temporary function GetAppUDF  as 'com.test.Hive.udf.GetAppUDF'; 

然后我们运行

  移除点击此处添加图片说明文字

​我靠,然后我desc safedata.apk_use

发现

  移除点击此处添加图片说明文字

​array<struct<apk:string,n:string,v:string,v_n:string,c:int,t:int>>

这种格式的字段,我第一次见到。

然后咱们查资料发现这么个东西:

  移除点击此处添加图片说明文字

​暂且理解为全部强制性读进来。

但是这回报错:

  移除点击此处添加图片说明文字

​这个到底是怎么回事呢?

原来是因为我们复制了很多>

  移除点击此处添加图片说明文字

​那好,我们把>删掉,重来。

select  uuid,GetAppUDF(apk_use),pt from safedata.apk_use limit 100;

结果:

FAILED: SemanticException [Error 10014]: Line 3:1 Wrong arguments 'apk_use': No matching method for class com.test.Hive.udf.GetAppUDF with (array<struct<apk:string,n:string,v:string,v_n:string,c:int,t:int>>). Possible choices: _FUNC_(string)  

原因就是这个格式,很恶心, array<struct<apk:string,n:string,v:string,v_n:string,c:int,t:int>>

卡了很久,怎么办呢。

卡住了很久,我感觉要来个狠得。请看

  移除点击此处添加图片说明文字

​结果气得想吐学:

  移除点击此处添加图片说明文字

​java也这么蠢啊,好难受,妈的。

去网上找大神操作吧。

  移除点击此处添加图片说明文字

​还是老样子,卡在这里快一到两个小时了,问了一下老大,他也不知道,让我研究。那好吧,继续研究吧。

我们看一篇文章:

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:

package com.lxw1234.hive.udf; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.MD5Hash; import org.apache.hadoop.hive.ql.exec.UDF; public class HashMd5 extends UDF { public String evaluate(String cookie) { return MD5Hash.getMD5AsHex(Bytes.toBytes(cookie)); } }

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

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

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

具体文章我粘贴一下地址:

http://www.cnblogs.com/1130136248wlxk/articles/5519276.html

GenericUDF

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

publicvoid 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完成后,执行关闭操作

所以我们新写一个类吧。

  移除点击此处添加图片说明文字

​然后我们改写之后,出现:

  移除点击此处添加图片说明文字

add jar /opt/workspace/udf/GetAppUDF.jar;

create temporary function GetAppUDF  as 'com.test.Hive.udf.GetAppUDF2'; 

select  uuid,GetAppUDF(apk_use),pt from safedata.apk_use limit 100; 

但是,我们看到还是这个问题啊、

Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/json/JSONArray

那接下来该怎么办,只能重新想办法了。

后来我想到了一个好的点子,卡了一整个下午,我就在向着怎么会找不到json类,一个原因是真的转不了,还有一个可能就是,根本没有接收到参数,所以空,也会报这个错。那么我换个巧妙地方式,你不是要微博的数据吗。那我这样。

  移除点击此处添加图片说明文字

​可以,很巧妙,发布试一下:

  移除点击此处添加图片说明文字

那我们把object换成String把。重新发布。​

但是:Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassCastException: java.lang.String cannot be cast to [Ljava.lang.Object;

这个其实就是转换错误的,我们看看程序吧。

我靠你大爷的,改了好久好久我的天:

  移除点击此处添加图片说明文字

卡了太久了。受不了了。然后我思考了很久,发现了这个代码

  移除点击此处添加图片说明文字

​细心的发现了这个是list,我靠,坑啊,血坑。

//return ObjectInspectorFactory.getStandardListObjectInspector(returnOI);

return returnOI;

  移除点击此处添加图片说明文字

​给力了。我的哥。

好了,接下来开发。

add jar /opt/workspace/udf/GetAppUDF.jar;

create temporary function GetAppUDF  as 'com.test.Hive.udf.GetAppUDF2'; 

drop table testing.testweiboudf;

create table testing.testWeiboUDF as select im,is,uuid,GetAppUDF(apk_list) ifWeibo,dt,pt from safedata.apk_list where apk_list is not null;

  移除点击此处添加图片说明文字

​好像有不少任务,

  移除点击此处添加图片说明文字

​等到hive转化的mapreduce跑完了,就可以了。

  移除点击此处添加图片说明文字

​然后我们发现全量表切割后,字段全部为false。

那简单,我们换一个应用试一试,换唯品会吧,或者是别的什么的。

  移除点击此处添加图片说明文字

​如果换成“微博”还不行,要么就是utf-8的事情,要么,就真的没有微博,接下来就换别的试试了,没有办法了。只能如此。等等跑完了看看吧,这个udf有点恶心。

  移除点击此处添加图片说明文字

这就很尴尬了,我们换一个。看看到底怎么回事。然后我试了一试别的,发现怎么都是false,这就有问题了。

这个中间报了个这么错:

  移除点击此处添加图片说明文字

​因为是那种特殊数组格式,我们得加一个is not null

改好了之后,还是这样,算了,先告一段落吧,下午要开发python爬虫了,没时间搞这个了,先停一段落吧。等这周后期,咱们再整这个吧,现在就差一点点了。后面如果有时间我们再把这个array<struct<>>解析一下吧。

其实简单的udf很好写,就是重写一个 evaluate函数,然后用参数取得字段值,分解,复杂的这个,继承GenericUDF,重写三个方法,initialize、evaluate、getdisplayString

转载请注明原文地址: https://www.6miu.com/read-61707.html

最新回复(0)