Hive3.1.2版本的UDF开发教程

一、UDF简介

1、UDF函数:

UDF(User-Defined Functions)即是用户定义的hive函数。hive自带的函数并不能完全满足业务需求,这时就需要我们自定义函数了。

2、UDF的分类:

UDF:one to one,进来一个出去一个,row mapping。是row级别操作,如:upper、substr函数
UDAF:many to one,进来多个出去一个,row mapping。是row级别操作,如sum/min。
UDTF:one to many ,进来一个出去多个。如alteral view与explode

二、编写UDF程序

1、创建maven功能,然后再pom.xml内引入hive的依赖:


	org.apache.hive
	hive-exec
	3.1.2



	org.apache.hive
	hive-jdbc
	3.1.2

2、继承类org.apache.hadoop.hive.ql.udf.generic.GenericUDF实现evaluate()函数

package io.myudf;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.MapredContext;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

@Description(name = "mysplit", 
value = "_FUNC_() - Returns a list by split string use character ',' ", 
extended = "Example:\n >SELECT _FUNC_('Hello,world,tang') FROM src LIMIT 1;\n  [\"hello\",\"world\",\"tang\"]")
public class Mysplit2 extends GenericUDF {

	@Override
	public void configure(MapredContext context) {
	}

	@Override
	public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
		// 定义函数的返回类型为java的List
		ObjectInspector returnOI = PrimitiveObjectInspectorFactory
				.getPrimitiveJavaObjectInspector(PrimitiveObjectInspector.PrimitiveCategory.STRING);
		return ObjectInspectorFactory.getStandardListObjectInspector(returnOI);
	}

	@Override
	public Object evaluate(DeferredObject[] arguments) throws HiveException {
		if (arguments.length != 1) {
			throw new UDFArgumentLengthException(" arguments length must be equal to 1");
		}

		String str = arguments[0].get().toString();
		String[] s = str.split(",", -1);

		return new ArrayList(Arrays.asList(s));
	}

	@Override
	public String getDisplayString(String[] children) {
		return "Usage: mysplit(String str)";
	}

}

3、使用mvn package命令打包,得到jar文件:myudf-0.0.1-SNAPSHOT.jar

mvn clean && mvn package
$ ll target/
total 8
drwxr-xr-x 1 tang 197121    0 Jul 16 21:53 classes/
drwxr-xr-x 1 tang 197121    0 Jul 16 21:51 generated-sources/
drwxr-xr-x 1 tang 197121    0 Jul 16 21:51 generated-test-sources/
drwxr-xr-x 1 tang 197121    0 Jul 16 21:53 maven-archiver/
drwxr-xr-x 1 tang 197121    0 Jul 16 21:50 maven-status/
-rw-r--r-- 1 tang 197121 4259 Jul 16 21:53 myudf-0.0.1-SNAPSHOT.jar
drwxr-xr-x 1 tang 197121    0 Jul 16 21:53 surefire-reports/
drwxr-xr-x 1 tang 197121    0 Jul 16 21:51 test-classes/

三、将jar包上传到hdfs

最好将jar文件放到hdfs上(示例中直接上传到HDFS的根目录下),这样可以实现一次性部署:

hdfs dfs -put myudf-0.0.1-SNAPSHOT.jar /
hadoop dfs -ls hdfs://node1:9000/

四、在Hive上安装UDF

使用hive或beeline等客户端工具登录到hive上,然后使用add jar命令将hdfs上的jar文件添加到hive的classpath中;通过使用create function命令创建函数(示例创建的函数名为:mysplit) ,使用desc function命令查看函数详情,然后即可在SQL中使用自定义的函数了。

hive
hive> add jar hdfs://node1:9000/myudf-0.0.1-SNAPSHOT.jar;
hive> use tangyibo;
hive> create function mysplit as 'io.myudf.Mysplit';
hive> desc function mysplit;
hive> desc function extended mysplit;
hive> select mysplit('hello,world,tang');

当然也可以使用如下命令删除函数:

hive> use tangyibo;
hive> drop function mysplit;

注意:用户自定义的函数只能在一个库内有效,即上述示例在库tangyibo中创建了自定义函数mysplit,那么该函数只在库tangyibo内可见,在其他库内不可见:

hive> use demo;
OK
Time taken: 0.055 seconds
hive> select mysplit('1,2,3');
FAILED: SemanticException [Error 10011]: Invalid function mysplit

你可能感兴趣的:(Hadoop)