Hive 中的自定义函数(udf,udtf,udaf)

自定义函数的类前面的注释,会在hive中desc中显示自定义函数的doc

@Description(
        name = "myudf",
        value = "这是一个自定义方法",
        extended = "eg: select myudf(1,2) => 3 , select myudf(\"hello\",\"world\") => helloworld"
)

导入包:hive-exec

 

 

1.UDF //user define function  

              //输入单行,输出单行,类似于 format_number(age,'000')

继承UDF 重新方法

import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;


@Description(
        name = "myudf",
        value = "",
        extended = "eg: select myudf(1,2) => 3 , select myudf(\"hello\",\"world\") => helloworld"
)

public class MyUDF extends UDF {

    public int evaluate(int i , int j){
        return i+j;
    }

    public String evaluate(String a, String b){
        return a+b;
    }
}

 

 

 

2.UDTF      //user define table-gen function

              //输入单行,输出多行,类似于 explode(array);

       1、通过initialize的参数(方法参数)类型或参数个数,

       2、返回输出表的表结构(字段名+字段类型)

       3、通过process函数,取出参数值,

       4、进行处理后通过forward函数将其输出

实现方法:继承GenericUDTF,实现initialize和process方法.,其中initialize方法里返回值定义了表结构,也就是函数执行完成之后定义为了一个新的虚拟的表,StructObjectInspector也就是结构对象,initialize方法的参数argOIs是输入字段的字段类型.而process是函数中真正生成数据的阶段.



import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
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.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

import java.util.ArrayList;
import java.util.List;

public class MyUDTF extends GenericUDTF {

    PrimitiveObjectInspector poi;

    //定义了表结构
    //argOIs => 输入字段的字段类型
    @Override
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {

        if (argOIs.getAllStructFieldRefs().size() != 1) {
            throw new UDFArgumentException("参数个数只能为1");
        }

        //如果输入字段类型非String,则抛异常
        ObjectInspector oi = argOIs.getAllStructFieldRefs().get(0).getFieldObjectInspector();//获取所有输入参数中的第//一个参数

        if (oi.getCategory() != ObjectInspector.Category.PRIMITIVE) {
            throw new UDFArgumentException("参数非基本类型,需要基本类型string");

        }
        //强转为基本类型对象检查器
        poi = (PrimitiveObjectInspector) oi;
        if (poi.getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING) {
            throw new UDFArgumentException("参数非string,需要基本类型string");
        }

        //构造表的字段名name
        List<String> fieldNames = new ArrayList<String>();
        fieldNames.add("name");


        //构造字段类型,string
        List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
        //通过基本数据类型工厂获取java基本类型oi
        fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);


        //构造对象检查器
        return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,
                fieldOIs);
    }


    //生成数据阶段
    @Override
    public void process(Object[] args) throws HiveException {
        //得到一行数据
        String line = (String) poi.getPrimitiveJavaObject(args[0]);

        String[] arr = line.split(" ");

        for(String name:arr){
            Object[] objs = new Object[1];
            objs[0] = name;//如果表的字段有多个时,objs[1] = xxx,init中表结构决定的
            forward(objs);//通过forward 将数据发送出去到定义的表结构中去
        }
    }


    //do nothing
    @Override
    public void close() throws HiveException {

    }
}
 

3.UDAF     //user define aggr function

              //输入多行,输出单行,类似于 sum(xxx)

 

 

注册自定义函数的三种方式:

       1、create function xxx as '自定义类的全路径';

 

       2、create temporary function xxx as '自定义类的全路径'; //临时自定义函数,重启hive之后不再发挥作用

 

       3、create function xxx as '' using jar 'hdfs://mycluster/xxx.jar'; //jar在hdfs上的位置

      

使用SparkSQL和Hive API,可以通过以下步骤实现用户自定义函数UDF)、聚合函数UDAF)和表生成函数UDTF): 1. 编写自定义函数的代码,例如: ``` // UDF def myUDF(str: String): Int = { str.length } // UDAF class MyUDAF extends UserDefinedAggregateFunction { override def inputSchema: StructType = StructType(StructField("value", StringType) :: Nil) override def bufferSchema: StructType = StructType(StructField("count", IntegerType) :: Nil) override def dataType: DataType = IntegerType override def deterministic: Boolean = true override def initialize(buffer: MutableAggregationBuffer): Unit = { buffer(0) = 0 } override def update(buffer: MutableAggregationBuffer, input: Row): Unit = { buffer(0) = buffer.getInt(0) + input.getString(0).length } override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = { buffer1(0) = buffer1.getInt(0) + buffer2.getInt(0) } override def evaluate(buffer: Row): Any = { buffer.getInt(0) } } // UDTF class MyUDTF extends GenericUDTF { override def initialize(args: Array[ConstantObjectInspector]): StructObjectInspector = { // 初始化代码 } override def process(args: Array[DeferedObject]): Unit = { // 处理代码 } override def close(): Unit = { // 关闭代码 } } ``` 2. 将自定义函数注册到SparkSQL或Hive,例如: ``` // SparkSQL注册UDF spark.udf.register("myUDF", myUDF _) // Hive注册UDF hiveContext.sql("CREATE TEMPORARY FUNCTION myUDF AS 'com.example.MyUDF'") // Hive注册UDAF hiveContext.sql("CREATE TEMPORARY FUNCTION myUDAF AS 'com.example.MyUDAF'") // Hive注册UDTF hiveContext.sql("CREATE TEMPORARY FUNCTION myUDTF AS 'com.example.MyUDTF'") ``` 3. 在SQL语句使用自定义函数,例如: ``` -- 使用SparkSQLUDF SELECT myUDF(name) FROM users -- 使用HiveUDF SELECT myUDF(name) FROM users -- 使用HiveUDAF SELECT myUDAF(name) FROM users GROUP BY age -- 使用HiveUDTF SELECT explode(myUDTF(name)) FROM users ``` 以上就是使用SparkSQL和Hive API实现用户自定义函数UDFUDAFUDTF)的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值