UDF

HIVE udf、udaf、udtf函数定义与用法(最全!!!!!) 一、定义 1、hive udf、udaf、udtf函数定义与用法 (1)UDF(user-defined function)作用于单个数据行,产生一个数据行作为输出。(数学函数,字符串函数) (2)UDAF(用户定义聚集函数 User- Defined Aggregation Funcation):接收多个输入数据行,并产生一个输出数据行。(count,max) (3)UDTF(表格生成函数 User-Defined Table Functions):接收一行输入,输出(explode) 总结: 阅读详情

  UDF函数用户自定义函数,在查询执行过程就是在Hive转换成MapReduce程序后,执行java方法,类似于像MapReduce执行过程中加入一个插件,方便扩展。Hive中有3种UDF:

  • UDF:操作单个数据行,产生单个数据行,如:upper、substr函数
  • UDAF:操作多个数据行,产生一个数据行,如sum、min函数
  • UDTF:操作一个数据行,产生多个数据行一个表作为输出,如 lateral view 、explode函数

  如果函数读和返回都是基础数据类型,即 Hadoop 和 Hive 的基本类型,如Text、IntWritable、LongWritable、DoubleWritable 等,那么继承 org.apache.hadoop.hive.ql.exec.UDF 。如果用来操作内嵌数据结构,如 Map、List 和 Set,则继承 org.apache.hadoop.hive.ql.udf.generic.GenericUDF。

用户构建的UDF使用过程如下:

  1. 继承UDF或者UDAF或者UDTF,实现特定的方法
  2. 将写好的类打包为jar,这里是WordTransferUDF.jar
  3. 进入到Hive shell环境中,输入命令add jar /home/hadoop/WordTransferUDF.jar注册该jar文件;或者把WordTransferUDF.jar上传到HDFS,hadoop fs -put WordTransferUDF.jar /home/hadoop/WordTransferUDF.jar,再输入命令add jar hdfs://hadoop01:8020/user/home/WordTransferUDF.jar
  4. 为该类起一个别名,create temporary function lower_udf as ‘UDF.lowerUDF’;注意,这里UDF只是为这个Hive会话临时定义的
  5. 在select中使用lower_udf()

自定义UDF

【pom.xml依赖】

<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.7.3</version>
</dependency>

【编写UDF代码】

package UDF;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public class WordTransferUDF extends UDF{
    /**
     * 1. Implement one or more methods named "evaluate" which will be called by Hive.
     * 2. "evaluate" should never be a void method. However it can return "null" if needed.
     */
    public Text evaluate(Text str){
        // input parameter validate
        if(null == str){
            return null ;
        }
        // validate
        if(StringUtils.isBlank(str.toString())){
            return null ;
        }
        // lower
        return new Text(str.toString().toLowerCase()) ;
    }
}

【打包】
注意 工程所用的jdk要与Hadoop集群使用的jdk是同一个版本
  
【注册UDF】

hive> add jar /home/hadoop/LowerUDF.jar
hive> create temporary function lower_udf as "UDF.LowerUDF";

【测试】

hive> create table test (id int ,name string);
hive> insert into test values(1,'TEST');
hive> select lower_udf(name) from test;

注意事项:

  1. 一个用户UDF必须继承org.apache.hadoop.hive.ql.exec.UDF
  2. 一个UDF必须要包含有evaluate()方法,但是该方法并不存在于UDF中。evaluate的参数个数以及类型都是用户自定义的。在使用的时候,Hive会调用UDF的evaluate()方法

GenericUDF

  GenericUDF API 提供了一种方法去处理那些不是可写类型的对象,例如:struct,map 和 array 类型。这个 API 需要用户亲自为函数的参数管理对象存储格式,验证接收的参数的数量与类型。这个 API 要求实现以下方法:

// 这个类似于简单 API 的 evaluate 方法,它可以读取输入数据和返回结果
abstract Object evaluate(GenericUDF.DeferredObject[] arguments);  
// 该方法应当是描述该 UDF 的字符串,显示函数的提示信息
abstract String getDisplayString(String[] children);  
// 只调用一次,在任何 evaluate() 调用之前,可以接收到一个可以表示函数输入参数类型的 object inspectors 数组
// 是用来验证该函数是否接收正确的参数类型和参数个数的地方
abstract ObjectInspector initialize(ObjectInspector[] arguments);  

例子来自 《Hive 编程指南》,编写一个用户自定义函数,称之为nvl(),这个函数传入的值如果是 null,那么就返回一个默认值。函数 nvl() 要求有 2 个参数。如果第 1 个参数是非null值,那么就返回这个值;如果第 1 个参数是 null,那么就返回第 2 个参数的值。

import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDFUtils;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;

public class GenericUDFNvl extends GenericUDF {
    private GenericUDFUtils.ReturnObjectInspectorResolver returnOIResolver;
    private ObjectInspector[] argumentOIs;
    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
        argumentOIs = arguments;
        // 1.检验参数个数
        if (arguments.length != 2) {
            throw new UDFArgumentException("The operator 'NVL' accepts 2 arguments.");
        }
        // 2.检验参数类型
        returnOIResolver = new GenericUDFUtils.ReturnObjectInspectorResolver(true);
        if (!(returnOIResolver.update(arguments[0]) && returnOIResolver.update(arguments[1]))) {
            throw new UDFArgumentTypeException(2, "The 1st and 2nd args of function NLV should have the same type, "
                    + "but they are different: \"" + arguments[0].getTypeName() + "\" and \"" + arguments[1].getTypeName() + "\"");
        }
        // 3.返回类型,和传入的参数类型一致
        return returnOIResolver.get();
    }
    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        Object retVal = returnOIResolver.convertIfNecessary(arguments[0].get(), argumentOIs[0]);
        if (retVal == null) {
            retVal = returnOIResolver.convertIfNecessary(arguments[1].get(), argumentOIs[1]);
        }
        return retVal;
    }
    @Override
    public String getDisplayString(String[] children) {
        StringBuilder sb = new StringBuilder();
        sb.append("if ");
        sb.append(children[0]);
        sb.append(" is null ");
        sb.append("returns ");
        sb.append(children[1]);
        return sb.toString();
    }
}

//测试
public class GenericUDFNvlTest {
    @Test
    public void testGenericUDFNvl() throws HiveException {
        // 建立需要的模型
        GenericUDFNvl example = new GenericUDFNvl();
        ObjectInspector stringOI1 = PrimitiveObjectInspectorFactory.javaStringObjectInspector;
        ObjectInspector stringOI2 = PrimitiveObjectInspectorFactory.javaStringObjectInspector;
        StringObjectInspector resultInspector = (StringObjectInspector) example.initialize(new ObjectInspector[]{stringOI1, stringOI2});
        // 测试结果
        Object result1 = example.evaluate(new GenericUDF.DeferredObject[]{new GenericUDF.DeferredJavaObject(null), new GenericUDF.DeferredJavaObject("a")});
        Assert.assertEquals("a", resultInspector.getPrimitiveJavaObject(result1));
        // 测试结果
        Object result2 = example.evaluate(new GenericUDF.DeferredObject[]{new GenericUDF.DeferredJavaObject("dd"), new GenericUDF.DeferredJavaObject("a")});
        Assert.assertNotEquals("a", resultInspector.getPrimitiveJavaObject(result2));
    }
}

自定义UDAF

UDAF 开发主要涉及到以下两个抽象类:

org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver
org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator

  大致上,UDAF 函数读取数据(mapper),聚集一堆 mapper 输出到部分聚集结果(combiner),并且最终创建一个最终的聚集结果(reducer)。因为需要对多个combiner 进行聚集,所以需要保存部分聚集结果。UDAF是需要在Hive的SQL语句和group by联合使用,Hive的group by 对于每个分组,只能返回一条记录,这点和MySQL不一样。开发通用UDAF有两个步骤:

  1. 编写resolver类,负责类型检查,操作符重载,里面创建evaluator类对象
  2. 编写evaluator类真正实现UDAF的逻辑
    【AbstractGenericUDAFResolver】
      Resolver 要覆盖实现 getEvaluator 方法,该方法会根据 sql 传人的参数数据格式指定调用哪个 Evaluator 进行处理。

【GenericUDAFEvaluator】
  UDAF 逻辑处理主要发生在 Evaluator 中,要实现该抽象类的几个方法。 ObjectInspector 接口与 GenericUDAFEvaluator 中的内部类 Model。

  • ObjectInspector:主要是解耦数据使用与数据格式,使数据流在输入输出端可以切换不同的输入输出格式,不同的 Operator上使用不同的格式
  • Model:Model 代表了 UDAF 在 mapreduce 的各个阶段
public static enum Mode {
    /**
     * PARTIAL1: 这个是mapreduce的map阶段:从原始数据到部分数据聚合
     * 将会调用iterate()和terminatePartial()
     */
    PARTIAL1,
        /**
     * PARTIAL2: 这个是mapreduce的map端的Combiner阶段,负责在map端合并map的数据:从部分数据聚合到部分数据聚合
     * 将会调用merge() 和 terminatePartial() 
     */
    PARTIAL2,
        /**
     * FINAL: mapreduce的reduce阶段:从部分数据的聚合到完全聚合 
     * 将会调用merge()和terminate()
     */
    FINAL,
        /**
     * COMPLETE: 如果出现了这个阶段,表示mapreduce只有map,没有reduce,所以map端就直接出结果了:从原始数据直接到完全聚合
      * 将会调用 iterate()和terminate()
     */
    COMPLETE
  };

一般情况下,完整的 UDAF 逻辑是一个 MapReduce 过程,如果有Mapper 和Reducer,就会经历 PARTIAL1(Mapper),FINAL(Reducer),如果还有 combiner,那就会经历 PARTIAL1(Mapper),PARTIAL2(combiner),FINAL(Reducer)。而有一些情况下的 Mapreduce,只有Mapper,而没有 Reducer,所以就会只有COMPLETE 阶段,这个阶段直接输入原始数据,出结果。

GenericUDAFEvaluator 的方法

// 确定各个阶段输入输出参数的数据格式 ObjectInspectors,一般负责初始化内部字段,通常初始化用来存放最终结果的变量
public  ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException;
 
// 保存数据聚集结果的类
abstract AggregationBuffer getNewAggregationBuffer() throws HiveException;
 
// 重置聚集结果
public void reset(AggregationBuffer agg) throws HiveException;
 
// map阶段,迭代处理输入sql传过来的列数据
public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException;
 
// map与combiner结束返回结果,得到部分数据聚集结果
public Object terminatePartial(AggregationBuffer agg) throws HiveException;
 
// combiner合并map返回的结果,还有reducer合并mapper或combiner返回的结果。
public void merge(AggregationBuffer agg, Object partial) throws HiveException;
 
// reducer阶段,输出最终结果
public Object terminate(AggregationBuffer agg) throws HiveException;

Model与Evaluator关系:Model 各阶段对应 Evaluator 方法调用
在这里插入图片描述
Evaluator 各个阶段下处理 mapreduce 流程
在这里插入图片描述
【demo】

package cn.wisec.meerkat.analyseOnHive;
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.parse.SemanticException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFParameterInfo;
import org.apache.hadoop.hive.ql.util.JavaDataModel;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.LongObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;

/**
 * 通常来说,顶层UDAF类继承{@link org.apache.hadoop.hive.ql.udf.generic.GenericUDAFResolver2}
 * 里面编写嵌套类evaluator实现UDAF的逻辑
 *
 * resolver通常继承org.apache.hadoop.hive.ql.udf.GenericUDAFResolver2,但是更建议继承AbstractGenericUDAFResolver,隔离将来hive接口的变化
 * GenericUDAFResolver和GenericUDAFResolver2接口的区别是:  后面的允许evaluator实现利用GenericUDAFParameterInfo可以访问更多的信息,例如DISTINCT限定符,通配符(*)。
 */
public class CountUDAF extends AbstractGenericUDAFResolver {
    @Override
    public GenericUDAFEvaluator getEvaluator(TypeInfo[] params) throws SemanticException {
        if (params.length > 1){
            throw new UDFArgumentLengthException("Exactly one argument is expected");
        }
        return new CountUDAFEvaluator();
    }
    /**
     * 这个构建方法可以判输入的参数是*号或者distinct
     */
    @Override
    public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo info) throws SemanticException {
        ObjectInspector[] parameters = info.getParameterObjectInspectors();
        boolean isAllColumns = false;
        if (parameters.length == 0){
            if (!info.isAllColumns()){
                throw new UDFArgumentException("Argument expected");
            }
            if (info.isDistinct()){
                throw new UDFArgumentException("DISTINCT not supported with");
            }
            isAllColumns = true;
        }else if (parameters.length != 1){
            throw new UDFArgumentLengthException("Exactly one argument is expected.");
        }
        return new CountUDAFEvaluator(isAllColumns);
    }
   
    public static class CountUDAFEvaluator extends GenericUDAFEvaluator{
        private boolean isAllColumns = false;
        /**
         * 合并结果的类型
         */
        private LongObjectInspector aggOI;
        private LongWritable result;
        public CountUDAFEvaluator() {}
        public CountUDAFEvaluator(boolean isAllColumns) {
            this.isAllColumns = isAllColumns;
        }
        /**
         * 负责初始化计算函数并设置它的内部状态,result是存放最终结果的
         * @param m 代表此时在map-reduce哪个阶段,因为不同的阶段可能在不同的机器上执行,需要重新创建对象partial1,partial2,final,complete
         * @param parameters partial1或complete阶段传入的parameters类型是原始输入数据的类型
         *                   partial2和final阶段(执行合并)的parameters类型是partial-aggregations(既合并返回结果的类型),此时parameters长度肯定只有1了
         * @return ObjectInspector
         *  在partial1和partial2阶段返回局部合并结果的类型,既terminatePartial的类型
         *  在complete或final阶段返回总结果的类型,既terminate的类型
         * @throws HiveException
         */
        @Override
        public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {
            super.init(m, parameters);
            //当是combiner和reduce阶段时,获取合并结果的类型,因为需要执行merge方法
            //merge方法需要部分合并的结果类型来取得值
            if (m == Mode.PARTIAL2 || m == Mode.FINAL){
                aggOI = (LongObjectInspector) parameters[0];
            }
            //保存总结果
            result = new LongWritable(0);
            //局部合并结果的类型和总合并结果的类型都是long
            return PrimitiveObjectInspectorFactory.writableLongObjectInspector;
        }
        /**
         * 定义一个AbstractAggregationBuffer类来缓存合并值
         */
        static class CountAgg extends AbstractAggregationBuffer{
            long value;
            /**
             * 返回类型占的字节数,long为8
             */
            @Override
            public int estimate() {
                return JavaDataModel.PRIMITIVES2;
            }
        }
        /**
         * 创建缓存合并值的buffer
         */
        @Override
        public AggregationBuffer getNewAggregationBuffer() throws HiveException {
            CountAgg countAgg = new CountAgg();
            reset(countAgg);
            return countAgg;
        }
        /**
         * 重置合并值
         */
        @Override
        public void reset(AggregationBuffer agg) throws HiveException {
            ((CountAgg) agg).value = 0;
        }
        /**
         * map时执行,迭代数据
         */
        @Override
        public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException {
            //parameters为输入数据
            //parameters == null means the input table/split is empty
            if (parameters == null){
                return;
            }
            if (isAllColumns){
                ((CountAgg) agg).value ++;
            }else {
                boolean countThisRow = true;
                for (Object nextParam: parameters){
                    if (nextParam == null){
                        countThisRow = false;
                        break;
                    }
                }
                if (countThisRow){
                    ((CountAgg) agg).value++;
                }
            }
        }
        /**
         * 返回buffer中部分聚合结果,map结束和combiner结束执行
         */
        @Override
        public Object terminatePartial(AggregationBuffer agg) throws HiveException {
            return terminate(agg);
        }
        /**
         * 合并结果,combiner或reduce时执行
         */
        @Override
        public void merge(AggregationBuffer agg, Object partial) throws HiveException {
            if (partial != null){
                //累加部分聚合的结果
                ((CountAgg) agg).value += aggOI.get(partial);
            }
        }
        /**
         * 返回buffer中总结果,reduce结束执行或者没有reduce时map结束执行
         */
        @Override
        public Object terminate(AggregationBuffer agg) throws HiveException {
            //每一组执行一次(group by)
            result.set(((CountAgg) agg).value);
            //返回writable类型
            return result;
        }
    }
}

使用:

hive> add jar /root/udf.jar
hive> create temporary function mycount as 'udf.CountUDAF'
hive> select call, mycount(*) as cn from beauty group by call order by cn desc
hive> select tag, mycount(tag) as cn from beauty lateral view explode(tags) lve_beauty as tag group by tag order by cn desc

自定义UDTF

UDTF用来解决输入一行输出多行的需求。限制:

  1. No other expressions are allowed in SELECT不能和其他字段一起使用:SELECT pageid,explode(adid_list) AS myCol… is not supported
  2. UDTF’s can’t be nested 不能嵌套:SELECT explode(explode(adid_list)) AS myCol… is not supported
  3. GROUP BY/ CLUSTER BY/ DISTRIBUTE BY/ SORT BY is not supported:SELECT explode(adid_list) AS myCol…GROUP BY myCol is not supported

继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,实现initialize,process,close三个方法。执行过程:

  1. UDTF首先会调用initialize方法,确定传入参数的类型并确定 UDTF 生成表的每个字段的数据类型(即输入类型和输出类型),主要是判断输入类型并确定返回的字段类型
  2. process:调用了 initialize() 后,Hive 将把 UDTF 参数传给 process() 方法,处理一条输入记录,输出若干条结果记录,该方法中,每一次调用 forward() 产生一行;如果产生多列可以将多个列的值放在一个数组中,然后将该数组传入到 forward() 函数
  3. close:在 process 调用结束后调用,用于进行其它一些额外操作,只执行一次,对需要清理的方法进行清理

给出实现explode函数的demo:explode会将一个数组中每个元素都输出一行,map中每对key-value都输出一行,实现对数据展开

package cn.wisec.meerkat.analyseOnHive;
import org.apache.hadoop.hive.ql.exec.TaskExecutionException;
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.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MyExplodeUDTF extends GenericUDTF {
    private transient ObjectInspector inputOI = null;
    /**
     * 初始化
     * 构建一个StructObjectInspector类型用于输出
     * 其中struct的字段构成输出的一行
     * 字段名称不重要,因为它们将被用户提供的列别名覆盖
     */
    @Override
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
        //得到结构体的字段
        List<? extends StructField> inputFields = argOIs.getAllStructFieldRefs();
        ObjectInspector[] udfInputOIs = new ObjectInspector[inputFields.size()];
        for (int i = 0; i < inputFields.size(); i++){
            //字段类型
            udfInputOIs[i] = inputFields.get(i).getFieldObjectInspector();
        }
        if (udfInputOIs.length != 1){
            throw new UDFArgumentLengthException("explode() takes only one argument");
        }
        List<String> fieldNames = new ArrayList<>();
        List<ObjectInspector> fieldOIs = new ArrayList<>();
        switch (udfInputOIs[0].getCategory()){
            case LIST:
                inputOI = udfInputOIs[0];
                //指定list生成的列名,可在as后覆写
                fieldNames.add("col");
                //获取list元素的类型
                fieldOIs.add(((ListObjectInspector) inputOI).getListElementObjectInspector());
                break;
            case MAP:
                inputOI = udfInputOIs[0];
                //指定map中key的生成的列名,可在as后覆写
                fieldNames.add("key");
                //指定map中value的生成的列名,可在as后覆写
                fieldNames.add("value");
                //得到map中key的类型
 fieldOIs.add(((MapObjectInspector)inputOI).getMapKeyObjectInspector());
                //得到map中value的类型
 fieldOIs.add(((MapObjectInspector)inputOI).getMapValueObjectInspector());
                break;
            default:`在这里插入代码片`
                throw new UDFArgumentException("explode() takes an array or a map as a parameter");
        }
        //创建一个Struct类型返回
        return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
    }
    //输出list
    private transient Object[] forwardListObj = new Object[1];
    //输出map
    private transient Object[] forwardMapObj = new Object[2];
    /**
     * 每行执行一次,输入数据args
     * 每调用forward,输出一行
     */
    @Override
    public void process(Object[] args) throws HiveException {
        switch (inputOI.getCategory()){
            case LIST:
                ListObjectInspector listOI = (ListObjectInspector) inputOI;
                List<?> list = listOI.getList(args[0]);
                if (list == null){
                    return;
                }
                //list中每个元素输出一行
                for (Object o: list){
                    forwardListObj[0] = o;
                    forward(forwardListObj);
                }
                break;
            case MAP:
                MapObjectInspector mapOI = (MapObjectInspector) inputOI;
                Map<?, ?> map = mapOI.getMap(args[0]);
                if (map == null){
                    return;
                }
                //map中每一对输出一行
                for (Map.Entry<?, ?> entry: map.entrySet()){
                    forwardMapObj[0] = entry.getKey();
                    forwardMapObj[1] = entry.getValue();
                    forward(forwardMapObj);
                }
                break;
            default:
                throw new TaskExecutionException("explode() can only operate on an array or a map");
        }
    }
    @Override
    public void close() throws HiveException {
    }
}

使用

hive> add jar /root/udtf.jar
hive> create temporary function myexplode as 'udf.MyExplodeUDTF'
hive> select myexplode(tags) as tag from beauty
hive> select myexplode(props) as (k,v) from beauty
hive> select tag, count(tag) as cn from beauty lateral view myexplode(tags) lve_beauty as tag group by tag order by cn desc 

永久函数

需要上传 jar 包到 HDFS目录中:

hadoop fs -put hive-udf.jar /user/hive/jars

然后进入 hive 中,创建函数:

hive> create function myFunction as 'udf' using jar 'hdfs:/user/hive/jars/hive-udf.jar';
Spark二次调用Hive UDF异常问题解决办法 异常如下: No handler for UDF/UDAF/UDTF 'com.******.***': java.lang.ClassNotFoundException: com.***; line 1 pos 7 org.apache.spark.sql.AnalysisException: No handler for UDF/UDAF/UDTF 'com.***': java.lang... 阅读详情

相关推荐

FLUENT中初识UDF——UDF的简单使用(1)

FLUENT中初识UDF——UDF的简单使用(1)注意:不包含其他ANSYS基本操作流程!!!1:UDF的编写:2:ANSYS中导入UDF函数:2.1:首先打开Fluent,导入UDF文件。2.2:给流体域设定UDF的运动。 注意:不包含其他ANSYS基本操作流程!!! 这里不过多的讲UDF语法,有许多视频已经将UDF讲的非常透彻,这里只是快速入门的教程。 注: ANSYS 2020 版本除适应中文外,很多地方已经不需要再使用UDF了! 1:UDF的编写: 没有C的可以直接使用 win系统自带的 ‘“记事本

asd1103810477的博客 6万+

COMSOL列管反应器模拟(包括多孔介质催化剂、化学反应、对流扩散、传热和对流换热)

COMSOL列管反应器模拟(包括多孔介质催化剂、化学反应、对流扩散、传热和对流换热)

qq_24800941的博客 9466

Doris Java UDF 最佳实践

Java UDF 为用户提供 UDF 编写的 Java 接口,以方便用户使用 Java 语言进行自定义函数的执行。

跟着大数据和AI去旅行 2057

UDF函数,hive调用java包简单方法

UDF函数,是hadoop在强大的大数据批量导入导出操作之余,为了满足复杂的数据逻辑操作留下的接口 核心思想:不管是UDF函数还是自定义处理jar包,都是要放置在hadoop服务器上的,相当于hadoop多出了一个自定义的处理数据的方法 1)其中调用的不管是参数还是数据库都是以hadoop本身的服务器环境路径为本地路径,而不是自己操作的java环境 2) 现在记录下2种近期使用过的...

weixin_30307267的博客 863

FLINK SQL UDF

在Flink SQL中,UDF(User-Defined Function,用户自定义函数)是一种扩展Flink SQL处理能力的机制。通过UDF,用户可以编写自定义的Java或Scala代码,以处理Flink SQL无法直接支持的数据处理逻辑。

王小工小工历程 2350

MaxCompute UDF

阿里云数仓离线UDF开发指南。

胜利的曙光的博客 2450

Hive UDF函数使用步骤

1.上传jar包到HDFS Hadoop fs -put local_path/test_udf.jar hdfs_path/test_udf.jar 2.创建Hive 永久函数 CREATEFUNCTIONdb_name.test_function_nameAS'com.baidu.traffic.udf.TestFunction'USING JAR'hdfs://hdfs_path/test_udf.jar'; 注:建议创建函数时指定库名,使用...

u011250186的博客 3117

UDF开发手册 - UDF

一行输入,返回一个结果 可以满足日常工作中的大部分需求 UDF的实现方法 Hive 提供了两个实现 UDF 的方式: 第一种:继承 UDF 类 优点: 实现简单 支持Hive的基本类型、数组和Map 支持函数重载 缺点: 逻辑较为简单,只适合用于实现简单的函数 这种方式编码少,代码逻辑清晰,可以快速实现简单的UDF 第二种:继承 GenericUDF 类 优点: 支持任意长度、任意类型的参数 可以根据参数个数和类型实现不同的逻辑 可以实现初始化和关闭资源的逻辑(initialize、cl

qq_38783098的博客 1604

Fluent UDF【5】:第一个UDF

这里以一个简单的初始化案例来描述UDF的使用过程。 0 Fluent中的Patch Fluent中提供了全域初始化以及局部Patch功能。对于整体区域的全局初始化可以采用starndard及hybrid方法进行初始化,指定各种物理量的初始分布。而对于计算域中的局部区域初始化,则可以通过Patch功能来实现。 在使用Patch方法时,需要实现对要进行Patch的区域进行标记。选择Mark/...

Charles_Li2014的博客 1999

Hive深入浅出UDF

Hive是一种构建在Hadoop上的数据仓库,Hive把SQL查询转换为一系列在Hadoop集群中运行的MapReduce作业,是MapReduce更高层次的抽象,不用编写具体的MapReduce方法,带来了很多便利,但是有时候hive提供的函数功能满足不了业务需要,就需要我们自己来写UDF函数来辅助完成。UDF函数其实就是一个简单的函数,执行过程就是在Hive转换成Mapreduce程序后,执行java方法,类似于像Mapreduce执行过程中加入一个插件,方便扩展。UDF只能实现一进一出的操作,如果需.

进击的数据小白 1704

MATLAB实战:蓝牙GFSK调制解调全流程解析(附误码率优化技巧)

本文深入解析了蓝牙GFSK调制解调在MATLAB中的全流程实现,包括高斯滤波器设计、调制解调技术及误码率优化技巧。通过实战案例和代码示例,帮助工程师提升蓝牙通信系统的性能表现,特别是在降低误码率方面的有效方法。

weixin_29046035的博客 277

Fluent UDF【7】:解释型UDF

UDF宏有两种方式可以被Fluent所接受:编译和解释。其中有一些宏既可以被解释也可以被编译,而一些宏则只能被解释。有一些场合只接受编译后的UDF(如动网格中的一些宏),而有些场合既可以接受编译的UDF,还能接受解释后的UDF。那么解释型的UDF与编译型的UDF到底存在何种差异?本文主要描述解释型UDF,而编译型UDF涉及到的问题更多,我们留到下次再说。 解释型UDF 解释型UDF不需要...

Charles_Li2014的博客 2173

宇树G1嵌入式软件架构及技术实现

该架构通过硬件加速(FPGA)+确定性调度(RTX5)的组合,在1ms控制周期内完成从传感器采集到43轴输出的全链路处理,相比波士顿动力系统缩短40%的着地稳定时间。,结合ARM Cortex-R5与FPGA的异构计算能力,实现43自由度1kHz实时控制。

m0_60674045的博客 4311

hive之UDF编程详解

前言:本文详解介绍UDF编程过程,以及hive中创建UDF函数的两种方式 文章目录1.什么是udf1.1UDF分类2.UDF编程示列2.1pom依赖2.2UDF编程2.3打jar包3.创建UDF函数3.1创建临时的UDF函数3.2创建永久生效的UDF函数3.3编译hive支持自定义的UDF函数 1.什么是udf UDF(User-Defined Functions)即是用户自定义的hive函数。h...

君永夜 8291

VisionMaster字符检测避坑指南:为什么你的缺陷检测总误判?7个参数陷阱详解

本文深入剖析了海康VisionMaster在字符缺陷检测中导致误判的7个关键参数陷阱,包括二值化参数、最小字符面积与宽度、字符极性及缺陷判决参数等。通过药品喷码和PCB丝印等实战案例,提供了系统的调试心法与工作流,帮助工程师精准调参,有效降低误判率,提升检测稳定性。

rust6ferris的博客 1098

封包(一)(雷电模拟器+ProxyDroid+查尔斯3.93+WPE)

自从换了工作就没有给大家分享一些干活,在加上陪伴自己的孩子没有时间更新文章了,这只能在晚上给大家写文档了,我最近在游戏公司上班,研究封包。我把这些东西都做成了笔记,我想有些东西是大家都想弄明白d ...

寒梅独自开 1万+

fluent udf手册_FLUENT并行UDF案例

正文共:2618字9图 预计阅读时间:7分钟1 前言当计算网格数量巨大时,如果还用串行计算的话,可以把人耗死。此时用并行计算可以显著节省时间,笔者在实际应用中深有体会。同样一个案例(网格数量约200万),串行计算大约10秒钟迭代一次,而改用25核并行计算,约2秒钟迭代一次。其实在我看来,模拟计算一定程度上比的就是计算机性能。特别当遇到网格数量巨大,且物理模型复杂的计...

weixin_39603799的博客 6821

单相全桥逆变三种SPWM调制方式(单极/双极/倍频)到底怎么选?一篇讲透优缺点与选型

本文深入解析单相全桥逆变器中单极性、双极性和单极性倍频三种SPWM调制方式的原理与工程选型策略。通过对比开关损耗、谐波特性和驱动复杂度等关键指标,提供基于STM32的实战方案和选型框架,帮助工程师在新能源发电、电机驱动等应用中做出最优决策。

weixin_34046298的博客 803

MySQL的UDF

最近用到MySQL的UDF, 查了一下相关文献, 对用户用户实现function和Aggregate function的方法做个介绍.

shaoyiwenet的专栏 9802

别再手动折腾了!PICO Unity SDK 一键配置开发环境保姆级教程(含PDC串流调试)

本文详细介绍了PICO Unity SDK的一键配置功能,帮助开发者快速搭建VR开发环境。通过自动化配置流程,大幅减少手动设置时间,提升开发效率。文章还涵盖了PDC串流调试技巧和常见问题解决方案,是PICO VR开发的实用指南。

weixin_30335575的博客 450

ArtMate —— 美术公开课智能体开发全记录

本文档详细描述了一款专为中小学美术公开课设计的智能教学助手的开发过程。该智能体融合了多模态感知、自然语言交互、风格迁移与智能评价等技术,旨在辅助教师开展生动、高效的美术鉴赏与创作课程。全文包含需求分析、系统架构设计、核心模块代码实现、交互界面搭建及完整运行示例,并配有详尽的行内注释和设计思想阐述,为教育技术开发者提供一份可落地、可扩展的参考方案。

huanghm88的专栏 153

【Hive】Hive UDF

文章目录一、UDF 介绍二、UDF2.1、简单 UDF2.2、复杂 GenericUDF三、UDAF3.1、AbstractGenericUDAFResolver3.2、GenericUDAFEvaluator3.3、GenericUDAFEvaluator 的方法3.4、图解Model与Evaluator关系3.5、编码实例四、UDTF五、UDF 使用5.1、准备步骤5.2、临时添加 UDF5....

w1992wishes的博客 3623

开源项目-智能算法中台管理系统

智能算法中台管理系统,系统主要有样本中心,算法中心,模型中心等模块

u010479989的博客 2998

udf提权

udf提权 什么是udf udf = “user defined function”,即‘用户自定义函数’。是通过添加新函数,对MYSQL的功能进行扩充,性质就像使用本地MYSQL函数如abs()或concat()。udf在mysql5.1以后的版本中,存在于’mysql/lib/plugin’目录下,文件后缀为’.dll’ 如何使用udf? 假设我的udf文件名为‘udf.dll’,存放在Mysql根目录(通过select @@basedir可知)的‘lib/plugin’目录下。在udf中,我定义了名为

qq_43430261的博客 9610

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Spark UDF 性能陷阱:Python UDF 和 Scala UDF 差距有多大

Spark UDF 的性能陷阱,本质上是一个"跨语言边界"的问题。Java/Python 之间的数据搬运成本远远超过函数执行本身。阶段行动目标设计优先用 Spark 内置函数避免 UDF必需用 Pandas UDF(Arrow)批处理 + 零拷贝优化逻辑下推到 SQL 引擎如果你的 Spark 任务中出现了@udf装饰器,先问自己三遍——这个逻辑能不能用写?能不能用写?能不能用expr()写?如果答案都是"不能",证明你真的需要 UDF;但凡有一个"能",就把@udf。

2401_85575345的博客 6503

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

上一篇: DAG以及任务调度
下一篇: HBASE调优
K. Bob
博客等级 码龄8年 82粉丝 294原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值