第3节 hive高级用法:13、hive的函数

mac2022-06-30  75

4.2、Hive参数配置方式

Hive参数大全:

https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties

 

开发Hive应用时,不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率,或帮助定位问题。然而实践中经常遇到的一个问题是,为什么设定的参数没有起作用?这通常是错误的设定方式导致的。

 

对于一般参数,有以下三种设定方式:

l  配置文件

l  命令行参数

l  参数声明

 

配置文件:Hive的配置文件包括

l  用户自定义配置文件:$HIVE_CONF_DIR/hive-site.xml

l  默认配置文件:$HIVE_CONF_DIR/hive-default.xml

用户自定义配置会覆盖默认配置。

另外,Hive也会读入Hadoop的配置,因为Hive是作为Hadoop的客户端启动的,Hive的配置会覆盖Hadoop的配置。

配置文件的设定对本机启动的所有Hive进程都有效。

 

命令行参数:启动Hive(客户端或Server方式)时,可以在命令行添加-hiveconf param=value来设定参数,例如:

bin/hive -hiveconf hive.root.logger=INFO,console

这一设定对本次启动的Session(对于Server方式启动,则是所有请求的Sessions)有效。

 

参数声明:可以在HQL中使用SET关键字设定参数,例如:

set mapred.reduce.tasks=100;

这一设定的作用域也是session级的。

 

上述三种设定方式的优先级依次递增。即参数声明覆盖命令行参数,命令行参数覆盖配置文件设定。注意某些系统级的参数,例如log4j相关的设定,必须用前两种方式设定,因为那些参数的读取在Session建立以前已经完成了。

 

参数声明  >   命令行参数   >  配置文件参数(hive)

五、Hive函数

5.1、内置函数

内容较多,见《Hive官方文档》

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

1)查看系统自带的函数

hive> show functions;

2)显示自带的函数的用法

hive> desc function upper;

3)详细显示自带的函数的用法

hive> desc function extended upper;

 

5.2 Hive自定义函数

1)Hive 自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义UDF来方便的扩展。

2)当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user-defined function)。

3)根据用户自定义函数类别分为以下三种:

       (1)UDF(User-Defined-Function)

              一进一出

       (2)UDAF(User-Defined Aggregation Function)

              聚集函数,多进一出

              类似于:count/max/min

       (3)UDTF(User-Defined Table-Generating Functions)

              一进多出

              如lateral view explore()

4)官方文档地址

https://cwiki.apache.org/confluence/display/Hive/HivePlugins

5)编程步骤:

       (1)继承org.apache.hadoop.hive.ql. exec.UDF

       (2)需要实现evaluate函数;evaluate函数支持重载;

6)注意事项

       (1)UDF必须要有返回类型,可以返回null,但是返回类型不能为void;

       (2)UDF中常用Text/LongWritable等类型,不推荐使用java类型;

 

5.3、UDF开发实例

简单UDF示例

第一步:创建maven  java 工程,导入jar包
第二步:开发java类继承UDF,并重载evaluate 方法
第三步:将我们的项目打包,并上传到hive的lib目录下
第四步:添加我们的jar包

add jar /export/servers/hive-1.1.0-cdh5.14.0/lib/udf.jar;

第五步:设置函数与我们的自定义函数关联

create temporary function touppercase as 'cn.itcast.udf.ItcastUDF';

第六步:使用自定义函数

select touppercase('abc');

Json数据解析UDF开发(作业)

作业:

有原始json数据如下:

{"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"}

{"movie":"661","rate":"3","timeStamp":"978302109","uid":"1"}

{"movie":"914","rate":"3","timeStamp":"978301968","uid":"1"}

{"movie":"3408","rate":"4","timeStamp":"978300275","uid":"1"}

{"movie":"2355","rate":"5","timeStamp":"978824291","uid":"1"}

{"movie":"1197","rate":"3","timeStamp":"978302268","uid":"1"}

{"movie":"1287","rate":"5","timeStamp":"978302039","uid":"1"}

 

需要将数据导入到hive数据仓库中

我不管你中间用几个表,最终我要得到一个结果表:

movie

rate

timestamp

uid

1197

3

978302268

1

注:全在hive中完成,可以用自定义函数

第一步:自定义udf函数,将我们json数据给解析出来,解析成四个字段,整成一个\t分割的一行

第二步:注册我们的自定义函数

第三步:创建一个临时表,加载json格式的数据,加载到临时表里面的一个字段里面去

第四步:insert  overwrite  local  directory    将临时表当中的数据通过我们的自定义函数,给查询出来,放到本地路径下面去

第五步:通过load  data的方式,将我们得数据加载到新表当中去

 

答:

1. 在linux系统的路径/export/servers/moviedatas下,新建movie.csv,将原始的json数据保存到该文件下,作为原始数据。

2. 将原始数据载入到临时表movie1中:

load data local inpath '/export/servers/moviedatas/movie.csv' overwrite into table movie1;

3. 将转换后的数据存到本地目录transferedData中:

insert overwrite local directory '/export/servers/moviedatas/transferedData' row format delimited fields terminated by '\t' select transferJson(sourceData) from movie1;

4. 将转换后的数据插入到结果表movie表中:

load data local inpath '/export/servers/moviedatas/transferedData/000000_0' into table movie;

代码:

TransferJsonUDF : package cn.itcast.hive.udf;import org.apache.hadoop.hive.ql.exec.UDF;import org.apache.hadoop.io.Text;public class TransferJsonUDF extends UDF { /* 原始数据格式:{"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"} {"movie":"661","rate":"3","timeStamp":"978302109","uid":"1"} 注意:各个系统的换行标志: win 用 \r\n linux/unix 用 \n Mac OS 用 \r */ public Text evaluate(final Text s){ if(s == null) return null; String str = s.toString().replace("\"","").replace("{","").replace("}",""); String[] split = str.split("[\r\n]"); StringBuffer sb = new StringBuffer(); for(String tmp:split){ String[] split2 = tmp.split(","); for(int i=0; i < split2.length; i++){ //split2[i]的格式 movie:1193 if(i==split2.length-1){ sb.append(split2[i].split(":")[1]).append("\n"); }else{ sb.append(split2[i].split(":")[1]).append("\t"); } } } return new Text(sb.toString().substring(0,sb.toString().length()-1)); }// public static void main(String[] args) {// Text text = evaluate(new Text("{\"movie\":\"1193\",\"rate\":\"5\",\"timeStamp\":\"978300760\",\"uid\":\"1\"}\n" +// "{\"movie\":\"661\",\"rate\":\"3\",\"timeStamp\":\"978302109\",\"uid\":\"1\"}")); Text text = evaluate(new Text("{\"movie\":\"1193\",\"rate\":\"5\",\"timeStamp\":\"978300760\",\"uid\":\"1\"}")); Text text = evaluate(new Text(args[0]));// System.out.println(text.toString());// }}

 

 

转载于:https://www.cnblogs.com/mediocreWorld/p/11062148.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)