目标
- 创建伪表
- 自定义UDF函数
- MR解决数据倾斜的问题(引入)
- 行转列案例
- 列转行案例
- 使用hive实现wc
- 修改hadoop的URI带来的hive数据库路径问题
- 多文件多目录做wc或建表带来的问题
创建伪表
创建表dual
create table dual(a string);
创建数据并导入到表
touch dual.txt
echo 'X' >dual.txt
load data local inpath '/home/hadoop/data/dual.txt' overwrite into table dual;
自定义UDF函数
hive官网关于用户如何自定义UDF: https://cwiki.apache.org/confluence/display/Hive/HivePlugins1.
hive查看函数: show functions;
hive查看jar包: list jars;
首先,需要创建一个扩展UDF的新类,其中有一个或多个名为evaluate的方法
// 继承UDF
public class UDFPrintf extends UDF {
//方法重载
public void evaluate(){
System.out.println("你不要老婆吧");
}
public void evaluate(String name){
System.out.println(name + ",你要老婆不要?");
}
}对方法添加描述,先看系统的
hive (default)> desc function extended upper;
upper(str) - Returns str with all characters changed to uppercase
Synonyms: ucase
Example:
> SELECT upper('Facebook') FROM src LIMIT 1;
'FACEBOOK'
=================================================================
@Description(
name = "upper,ucase",
value = "_FUNC_(str) - Returns str with all characters changed to uppercase",
extended = "Example:\n > SELECT _FUNC_('Facebook') FROM src LIMIT 1;\n
'FACEBOOK'"
)我们仿照上面的给自定义的方法写个描述(Description)
@Description(
name = "my_printf,ucase",
value = "_FUNC_(str) - 返回一个名字加上字符串",
extended = "Example:\n > SELECT _FUNC_('老王') FROM src LIMIT 1;\n
'老王,你要老婆不要?'"
)打包上传到Linux,启动hive,jar包添加到class path,创建临时UDF函数,只能在当前session中有效
add jar /home/hadoop/lib/hive-client-1.0.0.jar;
create temporary function my_printf as 'org.hadoop.hive.UDF.UDFPrintf';
伪表使用自定义函数
select my_printf() from dual;
hello,小七
select my_printf("老王") from dual;
hello,老王上面的方法只能创建临时函数,我们接下来将会创建永久函数,需要把jar把上传到hdfs
hdfs dfs -mkdir /jar
hdfs dfs -put /home/hadoop/lib/hive-client-1.0.0.jar /jar
CREATE FUNCTION my_printf AS 'org.hadoop.hive.UDF.UDFPrintf' USING JAR 'hdfs:///jar/hive-client-1.0.0.jar';然后可以在多个窗口执行创建的永久函数
MR解决数据倾斜的思想
核心思想==>先加盐(随机数),再去盐(随机数)
public class skew { |
7_老王 |
行转列案例
实现部门号的所有学生格式为
(dept01,A laowang|wangwu) |
数据
laowang dept01 A
zhangsan dept02 A
lisi dept01 B
wangwu dept01 A
zhaoliu dept02 A创建表结构
create external table row2col(
name string,
dept string,
grade string
)
row format delimited
fields terminated by "\t";导入数据
load data local inpath '/home/hadoop/data/row2col.txt' into table row2col;
实现(dept01,A laowang|wangwu)
第一步组合dept和grade成dept_grade
select concat_ws(',',dept,grade) dept_grade,name from row2col;
第二步按dept_grade分组求collect_set()将返回的数组使用concat_ws()函数转成字符串
select
t.dept_grade,concat_ws('|',collect_set(t.name)) names
from
(select concat_ws(',',dept,grade) dept_grade,name from row2col) t
group by
t.dept_grade;collect_set()返回一个数组,concat_ws()返回一个指定字符切分数组的字符串
结果
dept_grade|names |
----------|----------------|
dept01,A |laowang|wangwu |
dept01,B |lisi |
dept02,A |zhangsan|zhaoliu|
列转行案例
实现所有课程的格式为
1 zhangsan 化学 |
数据
1,zhangsan,化学:物理:数学:语文
2,lisi,化学:数学:生物:生理:卫生
3,wangwu,化学:语文:英语:体育:生物建表
create external table col2row(
id int,
name string,
subjects array<string>
)
row format delimited
fields terminated by ","
collection items terminated by ":";导数据
load data local inpath '/home/hadoop/data/col2row.txt' into table col2row;
实现
select
id,name,subject
from
col2row
lateral view explode(subjects) t as subject;结果
id|name |subject|
--|--------|-------|
1|zhangsan|化学 |
1|zhangsan|物理 |
1|zhangsan|数学 |
1|zhangsan|语文 |
2|lisi |化学 |
2|lisi |数学 |
2|lisi |生物 |
2|lisi |生理 |
2|lisi |卫生 |
3|wangwu |化学 |
3|wangwu |语文 |
3|wangwu |英语 |
3|wangwu |体育 |
3|wangwu |生物 |
使用hive实现wc
数据
化学:物理:数学:语文:英语
化学:数学:生物:生理:卫生
化学:语文:英语:体育:生物
数学:语文:英语:体育:生物切分返回数组
select split(line,":") as subjects from wc
炸开数组返回单词
select
words
from
(select split(line,":") subjects from wc) as t
lateral view explode(t.subjects) t1 as words;每个单词分组求count()
select
t2.words,count(1)
from
(select
words
from
(select split(line,":") subjects from wc) as t
lateral view explode(t.subjects) t1 as words) t2
group by t2.words;
修改hadoop的URI带来的hive数据库路径问题
hive的数据保存在hadoop中,而hive的源数据保存在mysql中
这里就有一个问题,如果修改了hadoop的fs.defaultFS这个参数
<property> |
那么hive的元数据没有修改就会找mysql中保存的路径
*************************** 1. row *************************** |
这时候需要使用到一个命令metatool来将mysql中的元数据修改为新的仓库路径
-updateLocation <new-loc> <old-loc> |
多文件多目录做wc或建表带来的问题
我们查看一下hdfs中的目录结构
[hadoop@aliyun ~]$ hdfs dfs -ls /mdir/* |
存在嵌套目录,在做wc或者建表时,将会报错
create external table dir (name string) location '/mdir'; |
通过设置参数mapreduce.input.fileinputformat.input.dir.recursive
为true
来解决这个问题,该参数默认为false
select * from dir; |
可以直接在mapped-site.xml文件中直接配配置参数
<property> |