Hive与HDFS的映射关系是什么?
元数据的功能是什么,存储在什么位置?
metastore服务的功能是什么,怎么启动,端口是什么,Hive的服务端如何启动,端口是什么?
如何封装Hive的SQL脚本?
客户端
封装SQL
hive -e :执行命令行的SQL语句,少量的SQL语句
hive -f:执行SQL文件
传递参数:–hiveconf
Hive中load与insert的命令的功能是什么?
DDL、DQL:基本与MySQL一致的
DML
Hive支持行级的insert、update、delete
数据写入:将数据构建表的结构,通过SQL对数据进行处理
数据来源:大量的数据文件、分析处理的结果
写入方式
load:将文件关联到Hive表中
insert:保存Select语句的结果
Hive中表的类型有几种,关键字和特点分别是什么?
create [temporary] [external] table
管理表:默认表结构,必须手动删除,不会自动删除,如果删除,既删除元数据也删除对应的数据
临时表:temporary,如果创建的客户端断开,临时表会自动删除
外部表:external,如果删除,只删除元数据
表的结构==【重点】==
Hive中特殊语法
Hive中的函数【重点】
内置函数:字符串函数、日期函数、聚合函数、特殊函数、窗口函数
自定义函数
URL解析函数
侧视图的使用
集合展开函数
引入:建表语句
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
(
col1Name col1Type [COMMENT col_comment],
co21Name col2Type [COMMENT col_comment],
co31Name col3Type [COMMENT col_comment],
co41Name col4Type [COMMENT col_comment],
co51Name col5Type [COMMENT col_comment],
……
coN1Name colNType [COMMENT col_comment]
)
[PARTITIONED BY (col_name data_type ...)] --分区表结构
[CLUSTERED BY (col_name...) [SORTED BY (col_name ...)] INTO N BUCKETS] --分桶表结构
[ROW FORMAT row_format] -- 指定数据文件的分隔符
row format delimited fields terminated by '列的分隔符' -- 列的分隔符,默认为\001
lines terminated by '行的分隔符' --行的分隔符,默认\n
[STORED AS file_format] -- 指定文件的存储格式
[LOCATION hdfs_path] -- 用于指定表的目录所在位置,默认表的目录在数据库的目录下面
目标:了解Hive中普通表结构的特点及应用场景
路径
实施
Hive与HDFS的映射关系
Hive | HDFS |
---|---|
数据库 | 目录 |
表 | 目录 |
数据 | 文件 |
MapReduce处理的规则
select count(*) from table where id > 30;
step1:检索元数据,找到表对应的HDFS目录
step2:将**表的最后一级目录作为MapReduce程序的输入**
TextInputFormat.setInputPaths(job,path1,path2……)
普通表结构的特点及应用
结构
Hive数据仓库目录/数据库目录/表的目录/数据文件
/user/hive/warehouse/db_emp.db/tb_emp/emp.txt
特点
表的最后一级目录是表的目录
问题:如果是一张普通表的结构,手动将文件通过HDFS命令放入表的目录下,在表中能否读到?
应用
小结
MapReduce处理Hive表数据的规则?
普通表结构的特点和应用是什么?
语法
create table (
);
特点:表的最后一级目录是表的目录
应用:一般用于将原始的大数据文件映射成表的结构
目标:掌握Hive中分区表结构的特点及应用场景
路径
实施
普通表结构的问题
需求:现在有一张普通表,记录一年365天的数据,每天一个1G文件,现在需要对其中某一天的数据进行处理
创建普通表,加载数据到普通表中
/user/hive/warehouse /db_nginx.db /tb_nginx /2020-01-01.log
2020-01-02.log
……
2020-12-31.log
实现
select count(*) from tb_nginx where daystr='2020-05-01';
问题
解决思想:如果只读取5月1号的数据文件,就不用过滤,直接处理得到结果
分区表结构的设计
设计思想
本质
结构
普通表
数据仓库目录/数据库目录/表的目录/数据文件
/user/hive/warehouse /db_nginx.db /tb_nginx /2020-01-01.log
2020-01-02.log
……
2020-12-31.log
分区表
数据仓库目录/数据库目录/表的目录/分区目录/分区数据文件
/user/hive/warehouse /db_nginx.db /tb_nginx /daystr=2020-01-01 /2020-01-01.log
/daystr=2020-01-02 /2020-01-02.log
……
/daystr=2020-12-31 /2020-12-31.log
通过SQL进行过滤查询
select count(*) from tb_nginx where daystr='2020-05-01';
MapReduce:按照日期分区,过滤条件也是日期
特点
应用
小结
目标:实现分区表的构建及应用
路径
实施
静态分区
应用:数据文件本身就是按照分区的规则划分好的,直接创建分区表,加载每个分区的数据即可
步骤
实现
- 创建分区表
create table tb_emp_part1(
empno string,
ename string,
job string,
managerno string,
hiredate string,
salary double,
jiangjin double,
deptno string
)
partitioned by (department int)
row format delimited fields terminated by '\t';
load data local inpath '/export/data/emp10.txt' into table tb_emp_part1 partition (department=10);
load data local inpath '/export/data/emp20.txt' into table tb_emp_part1 partition (department=20);
load data local inpath '/export/data/emp30.txt' into table tb_emp_part1 partition (department=30);
查询数据
explain extended select count(*) as numb from tb_emp_part1 where department = 20;
查看元数据
- PARTITIONS
SDS
动态分区
应用:数据本身没有按照分区的规则划分,需要通过程序实现自动动态划分
步骤
实现
创建普通表
创建分区表
create table tb_emp_part2(
empno string,
ename string,
job string,
managerno string,
hiredate string,
salary double,
jiangjin double
)
partitioned by (dept string)
row format delimited fields terminated by '\t';
--开启动态分区
set hive.exec.dynamic.partition.mode=nonstrict;
insert into table tb_emp_part2 partition(dept)
select * from tb_emp ;
|
insert into table tb_emp_part2 partition(dept)
select ……,deptno from tb_emp ;
问题:上面这个代码是如何知道按照哪个字段进行自动分区的呢?
- 按照查询语句的最后一个字段
多级分区
创建多级分区表
create table tb_ds_source(
id string,
url string,
referer string,
keyword string,
type string,
guid string,
pageId string,
moduleId string,
linkId string,
attachedInfo string,
sessionId string,
trackerU string,
trackerType string,
ip string,
trackerSrc string,
cookie string,
orderCode string,
trackTime string,
endUserId string,
firstLink string,
sessionViewNo string,
productId string,
curMerchantId string,
provinceId string,
cityId string,
fee string,
edmActivity string,
edmEmail string,
edmJobId string,
ieVersion string,
platform string,
internalKeyword string,
resultSum string,
currentPage string,
linkPosition string,
buttonPosition string
)
partitioned by (daystr string,hourstr string)
row format delimited fields terminated by '\t';
加载多级分区数据
load data local inpath '/export/data/2015082818' into table tb_ds_source partition (daystr='20150828',hourstr='18');
load data local inpath '/export/data/2015082819' into table tb_ds_source partition (daystr='20150828',hourstr='19');
结果
查看分区的命令
show partitions tbname;
小结
目标:理解分桶表的设计思想及实现分桶表的测试
路径
*实施
Join的问题
分桶表的设计
思想:将大的数据按照规则划分为多份小数据,每份小的数据都走Map Join,减少每条数据的比较次数,提高性能
功能
本质:通过MapReduce底层的分区【Reduce的划分规则】将数据划分到多个文件中
结构
数据仓库目录/数据库目录/表的目录/分桶的文件数据
设计
流程
分桶表的实现
语法
clustered by :按照哪一列分桶
N:分几个桶,代表底层写入数据就有几个reduce
实现
开启配置
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
create table tb_emp_bucket(
empno string,
ename string,
job string,
managerno string,
hiredate string,
salary double,
jiangjin double,
deptno string
)
clustered by (deptno) into 3 BUCKETS
row format delimited fields terminated by '\t';
写入分桶表
insert overwrite table tb_emp_bucket
select * from tb_emp cluster by (deptno);
小结
目标:了解Hive中的join语法的使用
实施
inner join:内连接
select
a.empno,
a.ename,
b.deptno,
b.dname
from
tb_emp a join tb_dept b on a.deptno = b.deptno;
left outer join:左外连接
左边有,结果就有
select
a.empno,
a.ename,
b.deptno,
b.dname
from
tb_emp a left join tb_dept b on a.deptno = b.deptno;
right outer join:右外连接
右边有,结果就有
select
a.empno,
a.ename,
b.deptno,
b.dname
from
tb_emp a right join tb_dept b on a.deptno = b.deptno;
full join:全连接
两边任意一边又,结果就有
explain select
a.empno,
a.ename,
b.deptno,
b.dname
from
tb_emp a full join tb_dept b on a.deptno = b.deptno;
笛卡尔积
select a.*,b.* from a,b;
select a.*,b.* from a join b;
小结
Hive中ReduceTask个数
Number of reduce tasks not specified. Estimated from input data size: 1
In order to change the average load for a reducer (in bytes):\
#每个Reduce处理的数据量大小
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
#最多允许启动的reduce的个数
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
#设置reduce的个数
set mapreduce.job.reduces=<number>
```
set mapreduce.job.reduces = 2;
```
order by的功能
功能:全局排序
select empno,ename,deptno,salary from tb_emp order by salary desc;
- 问题:如果Reduce有多个,能否实现全局排序?
- 不能有多个Reduce,使用了order by,只会启动一个reduce
sort by的功能
功能:局部排序
用法:与order by是一致的
select empno,ename,deptno,salary from tb_emp sort by salary desc;
```
insert overwrite local directory '/export/data/sort' row format delimited fields terminated by '\t'
select empno,ename,deptno,salary from tb_emp sort by salary desc;
```
小结
distribute by
功能:用于干预底层的MapReduce,指定某个字段作为K2
语法
insert overwrite local directory '/export/data/distby' row format delimited fields terminated by '\t'
select empno,ename,deptno,salary from tb_emp distribute by deptno;
```
insert overwrite local directory '/export/data/distby' row format delimited fields terminated by '\t'
select empno,ename,deptno,salary from tb_emp distribute by deptno sort by salary desc;
```
distribute by 1 => 用于将所有数据进入一个Reduce中
distribute by rand() => 实现随机分区,避免数据倾斜
cluster by
小结
目标:了解Hive表中数组类型的定义及使用
实施
数据
vim /export/data/array.txt
zhangsan beijing,shanghai,tianjin
wangwu shanghai,chengdu,wuhan,haerbin
建表
create database db_complex;
use db_complex;
create table if not exists complex_array(
name string,
work_locations array<string>
)
row format delimited fields terminated by '\t'
COLLECTION ITEMS TERMINATED BY ',';
COLLECTION ITEMS TERMINATED BY ',' --用于指定数组中每个元素的分隔符
加载
load data local inpath '/export/data/array.txt' into table complex_array;
取值
--统计每个用户工作过的城市个数
select name,size(work_locations) as numb from complex_array;
--取出数组中单独的元素
select name,work_locations[0],work_locations[1] from complex_array;
小结
目标:了解Hive表中Map集合类型的定义及使用
实施
数据
vim /export/data/map.txt
1,zhangsan,唱歌:非常喜欢-跳舞:喜欢-游泳:一般般
2,lisi,打游戏:非常喜欢-篮球:不喜欢
建表
create table if not exists complex_map(
id int,
name string,
hobby map<string,string>
)
row format delimited fields terminated by ','
COLLECTION ITEMS TERMINATED BY '-' MAP KEYS TERMINATED BY ':';
COLLECTION ITEMS TERMINATED BY '-' --用于划分每个KV对
MAP KEYS TERMINATED BY ':'; --用户划分K和V的
加载
load data local inpath '/export/data/map.txt' into table complex_map;
取值
--统计每个人有几个兴趣爱好
select name,size(hobby) as numb from complex_map;
--取出每个人对唱歌的喜好程度
select name,hobby["唱歌"] as deep from complex_map;
小结
目标:了解Hive中分隔符的问题及实现正则加载数据
路径
实施
分隔符的问题
场景1:数据中的列的分隔符||,Hive不支持多字节分隔符
01||周杰伦||中国||台湾||男||七里香
02||刘德华||中国||香港||男||笨小孩
03||汪 峰||中国||北京||男||光明
04||朴 树||中国||北京||男||那些花儿
05||许 巍||中国||陕西||男||故乡
06||张靓颖||中国||四川||女||画心
07||黄家驹||中国||香港||男||光辉岁月
08||周传雄||中国||台湾||男||青花
09||刘若英||中国||台湾||女||很爱很爱你
10||张 杰||中国||四川||男||天下
场景2:数据中每列的分隔符不一致
1 zhangsan,18-male
2 lisi,20-female
场景3:数据字段中包含了分隔符
192.168.88.1 - - [24/Dec/2019:15:54:58 +0800] "POST /set/report/ HTTP/1.1" 404 1093
处理方案
正则加载
数据
vim /export/data/regex.txt
2019-08-28 00:03:00 tom
2019-08-28 10:00:00 frank
2019-08-28 11:00:00 jack
2019-08-29 00:13:23 tom
2019-08-29 10:00:00 frank
2019-08-30 10:00:00 tom
2019-08-30 12:00:00 jack
建表
正常创建
create table regex1(
timestr string,
name string
) row format delimited fields terminated by ' ';
load data local inpath '/export/data/regex.txt' into table regex1;
- 正则加载
```sql
create table regex2(
timestr string,
name string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^}]*) ([^ ]*)"
)
STORED AS TEXTFILE;
load data local inpath '/export/data/regex.txt' into table regex2;
```
小结
目标:掌握Hive中常用的内置函数
路径
实施
查看函数
列举
show functions;
查看函数的用法
desc function [extended] funName;
常用函数
聚合函数:count、sum、avg、max、min
条件函数:if、case when
字符串函数
日期函数
特殊函数
小结
目标:了解Hive中如何实现自定义函数
路径
实施
函数分类
自定义UDF函数
需求:24/Dec/2019:15:55:01 -> 2019-12-24 15:55:01
step1:自定义一个类,继承UDF类
step2:在类中至少实现一个evaluate方法定义处理数据的逻辑
step3:打成jar包,添加到hive的环境变量中
add jar /export/data/udf.jar;
step4:将类注册为函数
create temporary function transFDate as 'bigdata.itcast.cn.hive.udf.UserUDF';
step5:调用函数
select transFDate("24/Dec/2019:15:55:01");
自定义UDAF与UDTF
UDAF
step1:将类注册为函数
create temporary function userMax as 'bigdata.itcast.cn.hive.udaf.UserUDAF';
step2:调用函数
select userMax(cast(deptno as int)) from db_emp.tb_dept;
cast:强制类型转换函数
cast(列 as 类型)
UDTF
step1:将类注册为函数
create temporary function transMap as ‘bigdata.itcast.cn.hive.udtf.UserUDTF’;
- step2:调用函数
```sql
select transMap("uuid=root&url=www.taobao.com") as (userCol1,userCol2);
小结
目标:掌握parse_url_tuple函数的使用
路径
实施
URL的分析需求
URL的组成
https://
www.jd.com
/index.jsp
?
cu=true&utm_source=baidu-pinzhuan&utm_medium=cpc&utm_campaign=t_288551095_baidupinzhuan&utm_term=0f3d30c8dba7459bb52f2eb5eba8ac7d_0_d4905eaf846c46baa9a57cf05415fb29
URL的解析函数
数据
vim /export/data/lateral.txt
1 http://facebook.com/path/p1.php?query=1
2 http://www.baidu.com/news/index.jsp?uuid=frank
3 http://www.jd.com/index?source=baidu
create table tb_url(
id int,
url string
) row format delimited fields terminated by '\t';
--加载数据
load data local inpath '/export/data/lateral.txt' into table tb_url;
函数
使用
0: jdbc:hive2://node3:10000> select parse_url(url,'HOST') from tb_url;
+----------------+--+
| c0 |
+----------------+--+
| facebook.com |
| www.baidu.com |
| www.jd.com |
+----------------+--+
3 rows selected (0.22 seconds)
0: jdbc:hive2://node3:10000> select parse_url(url,'PATH') from tb_url;
+------------------+--+
| c0 |
+------------------+--+
| /path/p1.php |
| /news/index.jsp |
| /index |
+------------------+--+
3 rows selected (0.062 seconds)
0: jdbc:hive2://node3:10000> select parse_url(url,'QUERY') from tb_url;
+---------------+--+
| c0 |
+---------------+--+
| query=1 |
| uuid=frank |
| source=baidu |
+---------------+--+
3 rows selected (0.09 seconds)
0: jdbc:hive2://node3:10000> select parse_url_tuple(url,'HOST','PATH','QUERY') from tb_url;
+----------------+------------------+---------------+--+
| c0 | c1 | c2 |
+----------------+------------------+---------------+--+
| facebook.com | /path/p1.php | query=1 |
| www.baidu.com | /news/index.jsp | uuid=frank |
| www.jd.com | /index | source=baidu |
+----------------+------------------+---------------+--+
3 rows selected (0.157 seconds)
小结
目标:掌握Hive中lateral view侧视图的使用
路径
实施
UDTF函数的问题
select id,parse_url_tuple(url,'HOST','PATH','QUERY') from tb_url;
lateral view
功能:UDTF的结果构建成一个类似于视图的表,然后将原表中的每一行和UDTF函数输出的每一行进行连接,生成一张新的虚拟表
语法
select …… from tabelA lateral view UDTF(xxx) 别名 as col1,col2,col3……
实现
select
a.id,
b.host,
b.path,
b.query
from tb_url a lateral view parse_url_tuple(url,'HOST','PATH','QUERY') b as host,path,query;
小结
目标:掌握explode函数的用法
实施
功能
语法
explode( Map | Array)
实现
单独使用
select explode(work_locations) as loc from complex_array;
select explode(hobby) from complex_map;
- 侧视图连用
```sql
select
a.id,
a.name,
b.*
from complex_map a lateral view explode(hobby) b as hobby,deep;
```
小结
<properties>
<hadoop.version>2.7.5hadoop.version>
<mysql.version>5.1.38mysql.version>
<hive.version>2.1.0hive.version>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-commonartifactId>
<version>${hadoop.version}version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-clientartifactId>
<version>${hadoop.version}version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-hdfsartifactId>
<version>${hadoop.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>org.apache.hivegroupId>
<artifactId>hive-execartifactId>
<version>${hive.version}version>
dependency>
<dependency>
<groupId>org.apache.hivegroupId>
<artifactId>hive-commonartifactId>
<version>${hive.version}version>
dependency>
<dependency>
<groupId>org.apache.hivegroupId>
<artifactId>hive-cliartifactId>
<version>${hive.version}version>
dependency>
<dependency>
<groupId>org.apache.hivegroupId>
<artifactId>hive-jdbcartifactId>
<version>${hive.version}version>
dependency>
dependencies>
org.apache.hadoop
hadoop-common
${hadoop.version}
org.apache.hadoop
hadoop-client
${hadoop.version}
org.apache.hadoop
hadoop-hdfs
${hadoop.version}
mysql
mysql-connector-java
${mysql.version}
org.apache.hive
hive-exec
${hive.version}
org.apache.hive
hive-common
${hive.version}
org.apache.hive
hive-cli
${hive.version}
org.apache.hive
hive-jdbc
${hive.version}