Hive使用小建议;编写hive UDF方法小示例

Hive中,某些小技巧可以让我们的Job执行得更快,有时一点小小的改动就可以让性能得到大幅提升,这一点其实跟SQL差不多。

首先,Hive != SQL,虽然二者的语法很像,但是Hive最终会被转化成MapReduce的代码去执行,所以数据库的优化原则基本上都不适用于 Hive。也正因如此,Hive实际上是用来做计算的,而不像数据库是用作存储的,当然数据库也有很多计算功能,但一般并不建议在SQL中大量使用计算,把数据库只当作存储是一个很重要的原则

一、善用临时表

在处理海量数据时我们通常会对很多大表进行操作,基于Hadoop现在的局限性,不能像分布式并行数据库那样很好地在分布式环境利用数据局部性,Hadoop对于大表只能全表扫描并筛选数据,而每一次对大表的扫描都是苦不堪言的。(最后知道真相的我眼泪掉下来。。。)

所以我们会用到在编码中经常用到的重构技巧,提取公共变量,在Hive中,就是创建临时表。

例如:现在要对三个表ABC进行处理,Hive QL是:

select T1.*, T2.*

from(

    select id, name from A

) T1 join (

    select id, price, feedback, type from B

) T2 on(T1.id = T2.id)

;

select T1.*, T2.*

from (

    select id, type from C

) T1 join (

    select id, price, feedback, attribute from B

) T2 on(T1.id = T2.id)

;

这里A表和C表只会被扫描一次,而B表会被扫描两次,如果B表的数据量很大,那么扫描B表的时间将会占用很大一块。

这里我们可以先创建一个临时表:

create table temp_B as select id, price, feedback, type, attribute from B;

 

这个表只有B表的部分字段,所以大小会小很多,这里会对B表全表扫一遍。

然后可以用临时表和AC表做join运算:

select T1.*, T2.*

from (

    select id, name from A

) T1 join (

    select id, price, feedback, type from temp_B

) T2 on(T1.id = T2.id)

;

select T1.*, T2.*

from (

    select id, type from C

) T1 join (

    select id, price,feedback, attribute from temp_B

) T2 on(T1.id = T2.id)

;

这样任务的执行速度将会有极大提升!尽管看起来多了一条Hive QL,但是后两个任务需要扫描的数据将会变得很小。

二、一次执行多个COUNT

如果我们要对多种条件进行COUNT,可以利用case语句进行,这样一条Hive QL就可以完成了。

select count(case when type = 1 then 1 end), count(case when type = 2 then 1 end) fromtable;

 

三、导出表文件

首先需要用create tableHDFS上生成你所需要的表,当需要从HDFS上将表对应的文件导出到本地磁盘时有两种方式:

1如果需要保持HDFS上的目录结构,原封不动地复制下来,采用下面的命令:

set hive.exec.compress.output='false';

insert overwrite local directory '/home/hesey/directory' select * from table;

这样下载下来的目录中会有很多由Reducer产生的part-*文件。

 

2、如果想把表的所有数据都下载到一个文件中,则采用下面的命令:

hadoop dfs -getmerge hdfs://hdpnn:9000/hesey/hive/table /home/hesey/table.txt

这样所有文件会由Hadoop合并后下载到本地,最后就只有/home/hesey/table.txt这一个文件。

四、UDF

Hive中很多时候都需要做一些复杂的计算或者逻辑处理,这时候Hive本身作为一个通用框架没法很好地支持,所以有了UDFUser Defined Function)。

1、使用UDF

a)如果是已经上传到Hive服务器的UDF,可以直接用

create temporary function dosomething as 'net.hesey.udf.DoSomething';

声明临时函数,然后在下面的Hive QL中就可以调用dosomething这个方法了。

b)如果是自己编写的UDF,需要在声明临时函数前再加一行:

add jar /home/hesey/foo.jar

这样就可以把自定义的UDF加载进来,然后和(a)一样声明临时函数就可以了。

2、编写UDF

编写UDF十分简单,引入hive-exec包,继承org.apache.hadoop.hive.ql.exec.UDF类,实现evaluate方法即可,方法的输入和输出参数类型就是当你在Hive中调用时的输入和返回值。

例如:

public Text evaluate(final LongWritable number);

TextLongWritableorg.apache.hadoop.io下面的类)

这样我们就可以定义自己的函数并方便地在Hive中调用,而不需要写一个重量级的MapReduce

五、笛卡尔积

Hive本身是不支持笛卡尔积的,不能用select T1.*, T2.* from table_1, table_2这种语法。但有时候确实需要用到笛卡尔积的时候,可以用下面的语法来实现同样的效果:

select T1.*, T2.*

from (

    select * from table1

) T1 join (

    select * from table2

) T2 on(1=1)

;

其中on 1=1是可选的,注意在HiveStrict模式下不能用这种语法,需要先用set hive.mapred.mode=nonstrict;设为非strict模式就可以用了。

六、join的规则

Hivejoin运算时,join前面的表会被放入内存,所以在做join时,最好把小表放在前面,有利于提高性能并防止OOM

七、排序

SQL中排序通过ORDER by实现,Hive中也支持这种语法,但是使用ORDER by时最终所有的数据会汇总到一个Reducer上进行排序,可能使得该Reducer压力非常大,任务长时间无法完成。

如果排序只要求保证Value有序而Key可以无序,例如要统计每个用户每笔的交易额从高到低排列,只需要对每个用户的交易额排序,而用户ID本身不需要排序。这种情况采用分片排序更好,语法类似于:

select user_id, amount from table distribute by user_id sort by user_id, amount

这里用到的不是ORDER by,而是distribute bysort bydistribute by标识Map输出时分发的Key

这样最后排序的时候,相同的user_idamount在同一个Reducer上被排序,不同的user_id可以同时分别在多个Reducer上排序,相比ORDER by只能在一个Reducer上排序,速度有成倍的提升。

 









编写udf:

HIVE允许用户使用UDF(user defined function)对数据进行处理。
用户可以使用‘show functions’ 查看function list,
可以使用'describe function function-name'查看函数说明。

hive> show functions;  
OK  
!  
!=  
......  
Time taken: 0.275 seconds
   
hive> desc function substr;  
OK  
substr(str, pos[, len]) - returns the substring of str that starts at pos and is of length len orsubstr(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len  
Time taken: 0.095 seconds  

hive> show functions;  
OK  
!  
!=  
......  
Time taken: 0.275 seconds 
 
hive> desc function substr;  
OK  
substr(str, pos[, len]) - returns the substring of str that starts at pos and is of length len orsubstr(bin, pos[, len]) - returns the slice of byte array that starts at pos and is of length len  
Time taken: 0.095 seconds  

hive提供的build-in函数包括以下几类:
1. 关系操作符:包括 = 、 <> 、 <= 、>=等
2. 算数操作符:包括 + 、 - 、 *、/等
3. 逻辑操作符:包括AND 、 && 、 OR 、 || 等
4. 复杂类型构造函数:包括map、struct、create_union等
5. 复杂类型操作符:包括A[n]、Map[key]、S.x
6. 数学操作符:包括ln(double a)、sqrt(double a)等
7. 集合操作符:包括size(Array)、sort_array(Array)等
8. 类型转换函数: binary(string|binary)、cast(expr as )
9. 日期函数:包括from_unixtime(bigint unixtime[, string format])、unix_timestamp()等
10.条件函数:包括if(boolean testCondition, T valueTrue, T valueFalseOrNull)等
11. 字符串函数:包括acat(string|binary A, string|binary B...)等
12. 其他:xpath、get_json_objectscii(string str)、con

编写Hive UDF有两种方式:
1. extends UDF , 重写evaluate方法
2. extends GenericUDF,重写initialize、getDisplayString、evaluate方法

hive有三种方法使用自定义的UDF函数
1. 临时添加UDF
如下:
hive> select * from test;       
OK  
Hello  
wORLD  
ZXM  
ljz  
Time taken: 13.76 seconds 
 
hive> add jar /home/work/udf.jar;                                               
Added /home/work/udf.jar to class path  
Added resource: /home/work/udf.jar  

hive> create temporary function mytest as 'test.udf.ToLowerCase';  
OK  
Time taken: 0.103 seconds  

hive> show functions;  
......  
mytest  
......  
hive> select mytest(test.name) from test;  
......  
OK  
hello  
world  
zxm  
ljz  
Time taken: 38.218 seconds  

hive> select * from test;       
OK  
Hello  
wORLD  
ZXM  
ljz  
Time taken: 13.76 seconds  

hive> add jar /home/work/udf.jar;                                               
Added /home/work/udf.jar to class path  
Added resource: /home/work/udf.jar  

hive> create temporary function mytest as 'test.udf.ToLowerCase';  
OK  
Time taken: 0.103 seconds 
 
hive> show functions;  
......  
mytest  
......  
hive> select mytest(test.name) from test;  
......  
OK  
hello  
world  
zxm  
ljz  
Time taken: 38.218 seconds  
这种方式在会话结束后,函数自动销毁,因此每次打开新的会话,都需要重新add jar并且create temporary function

2. 进入会话前自动创建
使用hive -i参数在进入hive时自动初始化

$ cat hive_init    
add jar /home/work/udf.jar;  
create temporary function mytest as 'test.udf.ToLowerCase';  
$ hive -i hive_init    
Logging initialized using configuration in file:/home/work/hive/hive-0.8.1/conf/hive-log4j.properties  
Hive history file=/tmp/work/hive_job_log_work_201209200147_1951517527.txt  

hive> show functions;  
......  
mytest  
......  
hive> select mytest(test.name) from test;  
......  
OK  
hello  
world  
zxm  
ljz  
[plain] view plaincopy
$ cat hive_init    
add jar /home/work/udf.jar;  
create temporary function mytest as 'test.udf.ToLowerCase';  
$ hive -i hive_init    
Logging initialized using configuration in file:/home/work/hive/hive-0.8.1/conf/hive-log4j.properties  
Hive history file=/tmp/work/hive_job_log_work_201209200147_1951517527.txt  
hive> show functions;  
......  
mytest  
......  
hive> select mytest(test.name) from test;  
......  
OK  
hello  
world  
zxm  
ljz  
方法2和方法1本质上是相同的,区别在于方法2在会话初始化时自动完成

3. 自定义UDF注册为hive内置函数
可参考:hive利器 自定义UDF+重编译hive
和前两者相比,第三种方式直接将用户的自定义函数作为注册为内置函数,未来使用起来非常简单,但这种方式也非常危险,一旦出错,将是灾难性的,因此,建议如果不是特别通用,并且固化下来的函数,还是使用前两种方式比较靠谱。

eg:
编写UDF代码实例(更多例子参考https://svn.apache.org/repos/asf/hive/tags/release-0.8.1/ql/src/java/org/apache/hadoop/hive/ql/udf/):
例子1:功能:大小转小写
ToLowerCase.java:

package test.udf;  
  
import org.apache.hadoop.hive.ql.exec.UDF;  
import org.apache.hadoop.io.Text;  
  
public class ToLowerCase extends UDF {  
    public Text evaluate(final Text s) {  
        if (s == null) { return null; }  
        return new Text(s.toString().toLowerCase());  
    }  
}  
[plain] view plaincopy
package test.udf;  
  
import org.apache.hadoop.hive.ql.exec.UDF;  
import org.apache.hadoop.io.Text;  
  
public class ToLowerCase extends UDF {  
    public Text evaluate(final Text s) {  
        if (s == null) { return null; }  
        return new Text(s.toString().toLowerCase());  
    }  
}  

例子2:功能:计算array中去重后元素个数
UDFArrayUniqElementNumbe r .java

package test.udf;  
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.serde2.objectinspector.ListObjectInspector;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;  
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;  
import org.apache.hadoop.io.IntWritable;  
  
 
@Description(name = "array_uniq_element_number", value = "_FUNC_(array) - Returns nubmer of objects with duplicate elements eliminated.", extended = "Example:\n"  
                + "  > SELECT _FUNC_(array(1, 2, 2, 3, 3)) FROM src LIMIT 1;\n" + "  3")  
public class UDFArrayUniqElementNumber extends GenericUDF {  
  
        private static final int ARRAY_IDX = 0;  
        private static final int ARG_COUNT = 1; // Number of arguments to this UDF  
        private static final String FUNC_NAME = "ARRAY_UNIQ_ELEMENT_NUMBER"; // External Name  
  
        private ListObjectInspector arrayOI;  
        private ObjectInspector arrayElementOI;  
        private final IntWritable result = new IntWritable(-1);  
  
        public ObjectInspector initialize(ObjectInspector[] arguments)  
                        throws UDFArgumentException {  
  
                // Check if two arguments were passed  
                if (arguments.length != ARG_COUNT) {  
                        throw new UDFArgumentException("The function " + FUNC_NAME  
                                        + " accepts " + ARG_COUNT + " arguments.");  
                }  
  
                // Check if ARRAY_IDX argument is of category LIST  
                if (!arguments[ARRAY_IDX].getCategory().equals(Category.LIST)) {  
                        throw new UDFArgumentTypeException(ARRAY_IDX, """  
                                        + org.apache.hadoop.hive.serde.Constants.LIST_TYPE_NAME  
                                        + "" " + "expected at function ARRAY_CONTAINS, but "  
                                        + """ + arguments[ARRAY_IDX].getTypeName() + "" "  
                                        + "is found");  
                }  
  
                arrayOI = (ListObjectInspector) arguments[ARRAY_IDX];  
                arrayElementOI = arrayOI.getListElementObjectInspector();  
  
                return PrimitiveObjectInspectorFactory.writableIntObjectInspector;  
        }  
  
        public IntWritable evaluate(DeferredObject[] arguments)  
                        throws HiveException {  
  
                result.set(0);  
  
                Object array = arguments[ARRAY_IDX].get();  
                int arrayLength = arrayOI.getListLength(array);  
                if (arrayLength <= 1) {  
                        result.set(arrayLength);  
                        return result;  
                }  
  
                //element compare; Algorithm complexity: O(N^2)  
                int num = 1;   
                int i, j;   
                for(i = 1; i < arrayLength; i++)  
                {  
                        Object listElement = arrayOI.getListElement(array, i);  
                        for(j = i - 1; j >= 0; j--)  
                        {  
                                if (listElement != null) {  
                                        Object tmp = arrayOI.getListElement(array, j);  
                                        if (ObjectInspectorUtils.compare(tmp, arrayElementOI, listElement,  
                                                        arrayElementOI) == 0) {  
                                                break;  
                                        }  
                                }  
                        }  
                        if(-1 == j)  
                        {  
                                num++;  
                        }  
                }  
  
                result.set(num);  
                return result;  
        }  
  
        public String getDisplayString(String[] children) {  
                assert (children.length == ARG_COUNT);  
                return "array_uniq_element_number(" + children[ARRAY_IDX]+ ")";  
        }  
}  


package test.udf;  
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.serde2.objectinspector.ListObjectInspector;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;  
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;  
import org.apache.hadoop.io.IntWritable;  
  
 
@Description(name = "array_uniq_element_number", value = "_FUNC_(array) - Returns nubmer of objects with duplicate elements eliminated.", extended = "Example:\n"  
                + "  > SELECT _FUNC_(array(1, 2, 2, 3, 3)) FROM src LIMIT 1;\n" + "  3")  
public class UDFArrayUniqElementNumber extends GenericUDF {  
  
        private static final int ARRAY_IDX = 0;  
        private static final int ARG_COUNT = 1; // Number of arguments to this UDF  
        private static final String FUNC_NAME = "ARRAY_UNIQ_ELEMENT_NUMBER"; // External Name  
  
        private ListObjectInspector arrayOI;  
        private ObjectInspector arrayElementOI;  
        private final IntWritable result = new IntWritable(-1);  
  
        public ObjectInspector initialize(ObjectInspector[] arguments)  
                        throws UDFArgumentException {  
  
                // Check if two arguments were passed  
                if (arguments.length != ARG_COUNT) {  
                        throw new UDFArgumentException("The function " + FUNC_NAME  
                                        + " accepts " + ARG_COUNT + " arguments.");  
                }  
  
                // Check if ARRAY_IDX argument is of category LIST  
                if (!arguments[ARRAY_IDX].getCategory().equals(Category.LIST)) {  
                        throw new UDFArgumentTypeException(ARRAY_IDX, """  
                                        + org.apache.hadoop.hive.serde.Constants.LIST_TYPE_NAME  
                                        + "" " + "expected at function ARRAY_CONTAINS, but "  
                                        + """ + arguments[ARRAY_IDX].getTypeName() + "" "  
                                        + "is found");  
                }  
  
                arrayOI = (ListObjectInspector) arguments[ARRAY_IDX];  
                arrayElementOI = arrayOI.getListElementObjectInspector();  
  
                return PrimitiveObjectInspectorFactory.writableIntObjectInspector;  
        }  
  
        public IntWritable evaluate(DeferredObject[] arguments)  
                        throws HiveException {  
  
                result.set(0);  
  
                Object array = arguments[ARRAY_IDX].get();  
                int arrayLength = arrayOI.getListLength(array);  
                if (arrayLength <= 1) {  
                        result.set(arrayLength);  
                        return result;  
                }  
  
                //element compare; Algorithm complexity: O(N^2)  
                int num = 1;   
                int i, j;   
                for(i = 1; i < arrayLength; i++)  
                {  
                        Object listElement = arrayOI.getListElement(array, i);  
                        for(j = i - 1; j >= 0; j--)  
                        {  
                                if (listElement != null) {  
                                        Object tmp = arrayOI.getListElement(array, j);  
                                        if (ObjectInspectorUtils.compare(tmp, arrayElementOI, listElement,  
                                                        arrayElementOI) == 0) {  
                                                break;  
                                        }  
                                }  
                        }  
                        if(-1 == j)  
                        {  
                                num++;  
                        }  
                }  
  
                result.set(num);  
                return result;  
        }  
  
        public String getDisplayString(String[] children) {  
                assert (children.length == ARG_COUNT);  
                return "array_uniq_element_number(" + children[ARRAY_IDX]+ ")";  
        }  
}  
生成udf.jar

例子3:
Hive中分组取前N个值的实现-row_number()

博客分类: Hive
Hive去重UDF 
背景
假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩。
这个就是典型在分组取Top N的需求。
 
解决思路
对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科,成绩做order by排序,然后对排序后的成绩,执行自定义函数row_number(),必须带一个或者多个列参数,如ROW_NUMBER(col1, ....),它的作用是按指定的列进行分组生成行序列。在ROW_NUMBER(a,b) 时,若两条记录的a,b列相同,则行序列+1,否则重新计数。
只要返回row_number()返回值小于100的的成绩记录,就可以返回每个单科成绩前一百的学生
 
Sql代码  
create table score_table (  
   subject            string,  
   student          string,  
   score                int  
)  
partitioned by (date string);  
Sql代码  
create table score_table (  
   subject            string,  
   student          string,  
   score                int  
)  
partitioned by (date string);  
 
如果要查询2012年每科成绩前100的学生成绩,sql如下
Java代码  
create temporary function row_number as 'com.blue.hive.udf.RowNumber';  
select subject,score,student from  
      (select subject,score,student from score where dt='2012'   order by subject,socre desc) order_score  
where row_number(subject) <= 100;  
Java代码  
create temporary function row_number as 'com.blue.hive.udf.RowNumber';  
select subject,score,student from  
      (select subject,score,student from score where dt='2012'   order by subject,socre desc) order_score  
where row_number(subject) <= 100;  
 
com.blue.hive.udf.RowNumber是自定义函数,函数的作用是按指定的列进行分组生成行序列。这里根据每个科目的所有成绩,生成序列,序列值从1开始自增。
 
执行row_number函数,返回值如下
科目   成绩 学生    row_number
物理   100 张一         1
物理   90   张二         2
物理   80   张三         3
.....
数学   100 李一         1
数学   90   李二         2
数学   80   李三         3
....
 
row_number的源码
函数row_number(),必须带一个或者多个列参数,如ROW_NUMBER(col1, ....),它的作用是按指定的列进行分组生成行序列。在ROW_NUMBER(a,b) 时,若两条记录的a,b列相同,则行序列+1,否则重新计数。

package com.blue.hive.udf;

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

public class RowNumber extends UDF {

    private static int MAX_VALUE = 50;
    private static String comparedColumn[] = new String[MAX_VALUE];
    private static int rowNum = 1;

    public int evaluate(Object... args) {
        String columnValue[] = new String[args.length];
        for (int i = 0; i < args.length; i++) 『
            columnValue[i] = args[i].toString();
        }
        if (rowNum == 1) {
            for (int i = 0; i < columnValue.length; i++)
                comparedColumn[i] = columnValue[i];
        }

        for (int i = 0; i < columnValue.length; i++) {
            if (!comparedColumn[i].equals(columnValue[i])) {
                for (int j = 0; j < columnValue.length; j++) {
                    comparedColumn[j] = columnValue[j];
                }
                rowNum = 1;
                return rowNum++;
            }
        }
        return rowNum++;
    }
}

编译后,打包成一个jar包,如/usr/local/hive/udf/blueudf.jar
然后在hive shell下使用,如下:
add jar /usr/local/hive/udf/blueudf.jar;
create temporary function row_number as 'com.blue.hive.udf.RowNumber';
select subject,score,student from
      (select subject,score,student from score where dt='2012'   order by subject,socre desc) order_score
where row_number(subject) <= 100;
 
同样,这个函数可以用作去重操作。
可以替代大批量数据的DISTINCT
通过执行如:
select * from(
select type,value,row_number() as rn 
from log_table    
distribute by type,value 
sort by type,value
)
where rn = 1;
  ===============注意!============================
但是使用row_number()函数需要注意一点,必须使用sort by。
测试的时候必须使用order by。
row_number()函数会假设数据有序的基础上进行的。











hive利器 自定义UDF+重编译hive
用hive也有一段时间里,不过一直没写过相关到日志,因为主要用hive也无非是create table,upload data,CRUD 这几个过程。后来工作中需要用到一些常用到方法,了解到hive中支持UDF(User Define Function),看里一些文章发现UDF到编写也很简单,继承UDF然后重写evaluate方法即可,下面以一个ip2long到方法作为参考。 
1.编写UDF类

import org.apache.hadoop.hive.ql.exec.UDF;
 
public class NewIP2Long extends UDF {
   public static long ip2long(String ip) {
 
       String[] ips = ip.split("[.]");
       long ipNum = 0;
       if (ips == null) {
           return 0;
       }
       for (int i = 0; i < ips.length; i++) {
           ipNum = ipNum << Byte.SIZE | Long.parseLong(ips[i]);
       }
 
       return ipNum;
   }
 
   public long evaluate(String ip) {
       if (ip.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")) {
           try {
               long ipNum = ip2long(ip);
               return ipNum;
           } catch (Exception e) {
               return 0;
           }
       } else {
           return 0;
       }
   }
 
   public static void main(String[] argvs) {
       NewIP2Long ipl = new NewIP2Long();
       System.out.println(ip2long("112.64.106.238"));
       System.out.println(ipl.evaluate("58.35.186.62"));
   }
}
 

2.编译,然后打包成ip2long.jar。 
3.在需要使用ip2long这个方法到时候:

1 add jar /tmp/NEWIP2Long.jar;
2 drop temporary function ip2long;
3 create temporary function ip2long as 'NewIP2Long';//如果类有包名,要加上包名
4 select ip2long(ip) from XXX ;
这种方法每次使用都要add,create一下,还是很麻烦,如果能把UDF编译到hive源码中那一定是件很high的事。 
进阶:将自定义UDF编译到hive中

重编译hive: 
   1)将写好的Jave文件拷贝到~/install/hive-0.8.1/src/ql/src/java/org/apache/hadoop/hive/ql/udf/

1 cd   ~/install/hive-0.8.1/src/ql/src/java/org/apache/hadoop/hive/ql/udf/
2 ls -lhgt |head
   2)修改~/install/hive-0.8.1/src/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java,增加import和RegisterUDF

1 import com.meilishuo.hive.udf.UDFIp2Long;    //添加import
2  
3 registerUDF("ip2long", UDFIp2Long.class, false); //添加register
   3)在~/install/hive-0.8.1/src下运行ant -Dhadoop.version=1.0.1 package

1 cd ~/install/hive-0.8.1/src
2 ant -Dhadoop.version=1.0.1 package
   4)替换exec的jar包,新生成的包在/hive-0.8.1/src/build/ql目录下,替换链接    

1 cp hive-exec-0.8.1.jar /hadoop/hive/lib/hive-exec-0.8.1.jar.0628
2 rm hive-exec-0.8.1.jar
3 ln -s hive-exec-0.8.1.jar.0628 hive-exec-0.8.1.jar
   5)重启hive服务 
   6)测试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值