impala可以自定义函数吗,怎么做?

2020-11-16 10:55发布

5条回答
乔治与佩奇
2021-12-20 17:12

1. 需求:统计impala 中字符串字符个数


前情:与hive  不同,impala 中的length ,char_Length 统计的是字符串中的字节个数,为了实现此需求使用自定义函数


问题关键点:正确计算,速度 


关于统计字符数正确:原本以为直接通过入参的length 就行,但是结果获得到的还是字节个数,也是很迷 (注明:impala 版本为cdh5.16中的2.12)


故写法如下:

 


package com.esen.spark;

import java.io.UnsupportedEncodingException;

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

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.Text;

public class Char_length extends UDF {

    /**

     * 如果返回值为 int时速度会更快 

     * @param regexstr

     * @return

     */

    public  IntWritable evaluate(Text regexstr) {

        if(regexstr!=null) {

            String str=null;

            try {

                str = new String(regexstr.getBytes(),"UTF-8");

            } catch (UnsupportedEncodingException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            return  new IntWritable(str.length());

        }else {

            return null;

        }

         

        //intWritable.set(str.toCharArray().length);

    }

 


在此代码中的关键点有两个: 1,利用byte 数组创建java 中utf8 字符串 2.使用匿名byte 数组   如果不使用匿名的数组,对于1.7亿数据而言,一个简单的select count(1) from a where charleng(b)>3 的时间在13分,使用匿名的函数时间则在10s


2.需求:实现与oracle 过滤方法相同的功能


oracle 过滤方法:


  FUNCTION F_CHANGE_CHR(V_NAME VARCHAR2) RETURN VARCHAR2 IS

    RESULT VARCHAR2(200);

  BEGIN

    RESULT := REGEXP_REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TO_SINGLE_BYTE(V_NAME),

                                                                                                                                                                      '(',

                                                                                                                                                                      ''),

                                                                                                                                                              ')',

                                                                                                                                                              ''),

                                                                                                                                                      '(',

                                                                                                                                                      ''),

                                                                                                                                              ')',

                                                                                                                                              ''),

                                                                                                                                      CHR(9),

                                                                                                                                      ''),

                                                                                                                              CHR(13),

                                                                                                                              ''),

                                                                                                                      '?',

                                                                                                                      ''),

                                                                                                              '?',

                                                                                                              ''),

                                                                                                      '《',

                                                                                                      ''),

                                                                                              '》',

                                                                                              ''),

                                                                                      '【',

                                                                                      ''),

                                                                              '】',

                                                                              ''),

                                                                      '—',

                                                                      ''),

                                                              '·',

                                                              ''),

                                                      ' ',

                                                      ''),

                                              '.',

                                              ''),

                                      ',',

                                      ''),

                              '<<',

                              ''),

                      '>>',

                      ''),'[[:punct:]]');

 

    RETURN RESULT;

  END;

问题难点:


在oracle 中,正则 [[:punct:]] 是过滤所有 特殊字符,但是在java 里面 \\p{Punct} 并不能达到相同效果,


impala 自定义函数最终实现:


// 实现全角转半角

 

// 写法说明: 由于impala 版本较低的原因,在evaluate 的参数 变为string,返回的结果不采用Text 进行转 //换的话,在impala 的查询结果为乱码,原因位置。但是后来我在impala 2.12 版本中并不会

public static Text evaluate(Text s) throws UnsupportedEncodingException {

if (s == null) {

return s;

} else {

Text result = new Text();

byte[] bs = s.getBytes();

String str = new String(bs, "UTF-8");

if (str.length() <= 0) {

return s;

} else {

char[] charArray = str.toCharArray();

//对全角字符转换的char数组遍历

for (int i = 0; i < charArray>

int charIntValue = (int) charArray[i];

//如果符合转换关系,将对应下标之间减掉偏移量65248;如果是空格的话,直接做转换

if (charIntValue >= 65281 && charIntValue <= 65374) {

charArray[i] = (char) (charIntValue - 65248);

} else if (charIntValue == 12288) {

charArray[i] = (char) 32;

}

}

result.set(new Text(new String(charArray)));

}

Text newchar=change_char(result);

return newchar;

}

}

// 字符过滤

    public static Text change_char(Text regexstr){

        Text returnstr=new Text();

        String targetstr=regexstr.toString();

        String target1= targetstr.

        replaceAll("[[\\pP|\\pS]&&[^―]]","").

      replaceAll("\\s*|\r|\t|\n","");

     

       returnstr.set(new Text(target1));

       return returnstr;

    }

一周热门 更多>