Hive 自定UDF函数,生成 32 位随机数
作者头像
  • 2019-11-15 07:04:10 7

曾经认为Hive自带的函数已经足够满足日常需求,未曾料到,还是会遇到需要自定义函数的情况。

需求非常明确:我需要模拟Oracle中的SYS_GUID()函数,生成一个32位的字母数字随机串。

以下是实现这一需求的代码:

```java import java.util.Random; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.hive.ql.udf.UDFType; import org.apache.hadoop.io.Text;

@UDFType(deterministic = false) public class HiveUDFOracleSysguid extends UDF { private Random random = new Random(); private Text result = new Text();

public Text evaluate(int length) {
    result.set(getCharAndNumr(length));
    return result;
}

private String getCharAndNumr(int length) {
    StringBuffer val = new StringBuffer();
    for (int i = 0; i < length; i++) {
        String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
        if ("char".equalsIgnoreCase(charOrNum)) {
            int choice = 65;
            val.append((char) (choice + random.nextInt(26)));
        } else if ("num".equalsIgnoreCase(charOrNum)) {
            val.append(String.valueOf(random.nextInt(10)));
        }
    }
    return val.toString();
}

} ```

部署步骤

步骤一:将该类打包,并上传至集群。

步骤二:将jar包添加到Hive的classpath中: sql hive> add jar /home/hive-tools-sysguid-for-oracle.jar;

步骤三:基于自定义UDF类创建自定义函数: sql hive> create temporary function sys_guid as 'cn.bigdata.tools.HiveUDFOracleSysguid'; 其中,sys_guid是自定义的函数名称,cn.bigdata.tools.HiveUDFOracleSysguid是类名。

执行查询

使用自定义函数的方式与内置函数相同: sql select sys_guid(32) from sp_t_re_valid_service limit 20;

解决问题记录

起初,按照上述模板编写代码,运行时遇到了一个问题:生成的随机串逻辑只被执行了一次,所有行的随机串都是相同的,而不是每一行都有不同的随机串。

这个问题困扰了很多人,查阅了许多关于UDF开发的文章也没有找到解决方案。最终,灵感来源于Hive内置的rand()函数,它能够为每行生成不同的随机数。因此,决定从rand()函数的源码中寻找答案。

rand()函数的核心逻辑位于org.apache.hadoop.hive.ql.udf类中,大家可以自行查阅。

将核心逻辑复制到自己的UDF中测试后,发现问题依旧存在,核心逻辑只被执行了一次。关键在于@UDFType(deterministic = false)注解,该注解用于指定UDF是否具有确定性,默认为true。而rand()函数的源码中,该属性被设置为false

经过测试,加入@UDFType(deterministic = false)注解后,UDF能够正常工作,每行都能生成不同的32位字母数字随机串。

    本文来源:图灵汇
责任编辑: :
声明:本文系图灵汇原创稿件,版权属图灵汇所有,未经授权不得转载,已经协议授权的媒体下载使用时须注明"稿件来源:图灵汇",违者将依法追究责任。
    分享
自定随机数函数生成HiveUDF32
    下一篇