第一章:上次课回顾
第二章:Hive DDL(分区表)
2.1 分区表简介
2.2 分区表的使用
- 2.2.1 第一种:创建分区表、把数据加载至分区
- 2.2.2 第二种:在hdfs上创建文件目录,上传文件,alter刷新分区信息
2.3 多级分区
2.4 动态分区
第三章:Hive的其它连接使用方式
第四章:Hive建表时的一些数据类型
零基础班第十六课 - Hive DML详解:
https://blog.csdn.net/zhikanjiani/article/details/89391164
回顾:上次课主要讲了如何把数据加载到Hive中去,对于离线批处理,要采用load的方式,而不是insert。
生产背景:BI人员从关系型数据库转型大数据,使用关系型数据库方式来操作大数据,在hive中采用insert方式插入后产生一堆小文件,
问:该如何处理?
在hive0.14版本后支持insert(性能不行,还会产生小文件),采用load方式加载,此时我们可以进行数据的查询,导出数据后期采用sqoop。
还讲了一些基本的SQL用法,groupby分组(select中出现的字段一定要在groupby中体现或在聚合函数中出现)
为什么采用分区表:
eg:举例拨打10086客服热线,我们按1 --> 业务查询 (第一层)–> 按1(余额查询)(第二层),我们的每一步操作都是有一条记录的;我们拨打人工,专席还会帮你转接;账号高级还会有专席来接听。
如果这些话务记录全部都存储到一张表上去,那就是等死,数据量是非常大的。
传统做法:日志记录会存储到关系型数据库,至少要做到分表(以天为单位进行分表)。
call_record_20190418 //4月18号的记录做一张表
call_record_20190419 //4月19号的记录做一张表
查询的话给定时间范围,就会去拼接表,相比查询整个表,性能肯定是高出不少的,比如select * from where day between 20190418 and 20190420;
举例:
1、有如下两张分区表:
/user/hive/warehouse/emp/d=20190418
/user/hive/warehouse/emp/d=20190419
2、查找d='20190418’这天的记录
select * from table where d=‘20190418’
3、这样的话不用去全表扫描,带来的性能提升是非常大的
瓶颈:IO:disk network 磁盘IO(像分区表这种方式就能减少很多的数据读取操作)和网络IO
查询的话可以以天为单位进行查询
前提:数据准备:
10703430736748 2018-04-01 06:01:15
10703430736749 2018-04-01 07:01:15
10703430736750 2018-04-01 08:01:15
10703430736751 2018-04-01 09:01:15
语法定义:
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name] table_name
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ....)]
开始创建order_partition分区表:
create table order_partition(
order_no string,
event_time string
) partitioned by(event_month string)
row format delimited fields terminated by '\t';
创建订单分区表,表中两个字段:订单编号字段以及订单时间字段;创建的分区表按月分隔;注意字段类型要写,’\t’指的是要加载进来的数据以tab键分割。
语法如下:
LOAD DATA LOCAL INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1), partcol2=val2....]
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] [INPUTFORMAT 'inputformat' SERDE 'serde'] (3.0 or later)
自己写SQL把数据加载进去:
load data local inpath '/home/hadoop/data/order.txt'
overwrite into table order_partiton
PARTITION(event_month='2019-04');
查询order_partition表信息:
1、查看我们创建的这个分区表的信息,然后我们发现数据是存储在/event_month=2019-04下面的。
2、真实数据是存放在如下路径下的:
路径:hadoop fs -ls /usr/hive/warehouse/g6.db/order_partition/event_month=2019-04
3、这个2019-04其实是一个伪列:
0、在hdfs上创建目录,把数据put上去
1、进入MySQL数据库,select * from partition;
2、47这张表中有2个分区,2019-05是我们手工创建的,需要刷新分区信息,才能够使它感知的到
语法:
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location'][, PARTITION partition_spec [LOCATION 'location'], ...];
刷新分区信息的SQL语句:
ALTER TABLE order_partition ADD IF NOT EXISTS PARTITION (event_month='2019-05')
我们一再强调Hive的数据一部分是在关系型数据库(元数据信息),另一部分是在hdfs上中;如果元数据信息中没有囊括进去,那我们是永远也查询不到的。
hive (ruozeg6)> show partitions order_partition;
OK
event_month=2019-05
event_month=2019-09
event_month=201904
Time taken: 0.155 seconds, Fetched: 3 row(s)
1、创建多级分区表
create table order_multi_partition(
order_no string,
event_time string
)
PARTITIONED BY(event_month string, step string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
2、加载数据
3、使用select查询语句:
一级分区、多级分区都是静态分区
本地data目录下有一份员工emp表,按照部门编号写到指定的分区中去
1、便捷的拷贝语句:show create table emp; //可以直接查看emp表的建表语法。
create table emp_static_partition(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double
) PARTITIONED BY (deptno int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
2、把数据写到emp_static_partition表中去:
Hive官网中insert的语法(insert是DML,所以去到Hive DML中去查找):
1、INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
2、INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
3、把emp表中deptno=20的如下字段取出来,插入到emp_static_partition中去,这个SQL执行是跑MapReduce的。
insert into table emp_static_partition PARTITION (deptno=20)
select empno,ename,job,mgr,hiredate,sal,comm from emp
where deptno=20;
这种SQL和3中的insert的SQL的区别
注意:禁止使用带VALUES的这种
4、SQL一查询数据就直接出来了
hive (ruozeg6)> select * from emp_static_partition where deptno = 20;
OK
7369 SMITH CLERK 7902 1980-02-15 200.0 NULL 20
7698 BLADE ANALYST 7658 1992-05-25 1300.0 NULL 20
7369 SMITH CLERK 7902 1980-02-15 200.0 NULL 20
7698 BLADE ANALYST 7658 1992-05-25 1300.0 NULL 20
1416 ron player 7643 1997-01-23 5000.0 1500.0 20
1415 erath IT 7528 1996-02-18 5500.0 1000.0 20
1416 zacker engineer 3628 1995-11-03 5800.0 NULL 20
Time taken: 2.129 seconds, Fetched: 7 row(s)
1、创建动态分区表(表名改掉即可),dept后面不跟值,第二行查出的是所有的员工信息,怎么对应上去,deptno在select的最后才能与之对应
SQL如下:
insert into table emp_dynamic_partition partiiton (deptno)
select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
运行SQL报错:
hive (ruozeg6)> insert into table emp_dynamic_partition partition (deptno)
> select empno,ename,job,mgr,hiredate,sal,comm,dept from emp;
FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict
2、直接在Hive中设置:set hive.exec.dynamic.partition.mode=nonstrict;
3、分别运行如下三个SQL:
1、要把hive.exec.dynamic.partition.mode这个模式关掉
2、一定要跟在select语句的最后
insert into table emp_dynamic_partition partiiton (deptno,step)
select empno,ename,job,mgr,hiredate,sal,comm,deptno,step from emp
insert的两种方式:
1、insert values //值的这种方式不能用
2、insert into tables select …
在我们启动Hive的过程中,注意一句话:
[hadoop@hadoop004 bin]$ pwd
/home/hadoop/app/hive/bin
[hadoop@hadoop004 bin]$ ll
total 32
-rwxr-xr-x. 1 hadoop hadoop 881 Mar 24 2016 beeline
drwxr-xr-x. 3 hadoop hadoop 4096 Mar 24 2016 ext
-rwxr-xr-x. 1 hadoop hadoop 7751 Mar 24 2016 hive
-rwxr-xr-x. 1 hadoop hadoop 1900 Mar 24 2016 hive-config.sh
-rwxr-xr-x. 1 hadoop hadoop 885 Mar 24 2016 hiveserver2
-rwxr-xr-x. 1 hadoop hadoop 832 Mar 24 2016 metatool
-rwxr-xr-x. 1 hadoop hadoop 884 Mar 24 2016 schematool
怎么找对应的网页目录:
1、hive.apaceh.org --> 2、Hive wiki --> 3、User Documentation --> 4、HiveServer2
启动服务还分为两种方式:前端和后端
1、前端的方式:直接进到$HIVE_HOME/bin目录下,使用命令:./hiveserver2
2、后端启动的方式:nohup
前端启动的不能关,关了服务就停了。
还是去官网上找:hiveserver2 + beeline
跳转到如下网址:https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients
通过clinet端连接到服务上需要哪些信息:
1、解读:-u jdbc:hive2:// 固定写法;hadoop004指的是机器的ip;10000是beeline的端口号;ruoze_g6是在hive-site.xml体现的;-n hadoop 指定的是hadoop机器的用户名(hostname)
启动Beeline(在$HIVE_HOME/bin目录下):
Connected to: Apache Hive (version 1.1.0-cdh5.7.0)
Driver: Hive JDBC (version 1.1.0-cdh5.7.0)
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 1.1.0-cdh5.7.0 by Apache Hive
每次在Client端(beeline)成功执行一个命令时,都会在Server端(./hiveserver2)返回一个ok
数据准备:
1、第一列是名字,和第二列以tab键进行分割
[hadoop@hadoop004 data]$ pwd
/home/hadoop/data
[hadoop@hadoop004 data]$ cat hive_array.txt
ruoze beijing,shanghai,tianjin,hangzhou
jepson changshu,chengdu,wuhan,beijing
2、建表语句如下:
hive (ruozeg6)> create table hive_array (
> name string,
> work_locations array
> )
> ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
OK
Time taken: 3.52 seconds
3、把数据导进来:
load data local inpath '/home/hadoop/data/hive_array.txt'
into table hive_array;
4、2中的建表语句漏了一个属性,删除表后重新建表,再把数据加载进来
hive (ruozeg6)> create table hive_array (
> name string,
> work_locations array
> )
> ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t"
> COLLECTION ITEMS TERMINATED BY ",";
OK
Time taken: 3.52 seconds
需求一
hive (ruozeg6)> select name,work_locations[0] from hive_array;
OK
ruoze beijing
jepson changshu
Time taken: 0.112 seconds, Fetched: 2 row(s)
hive (ruozeg6)> select name,work_locations[10] from hive_array;
OK
ruoze NULL
jepson NULL
Time taken: 0.095 seconds, Fetched: 2 row(s)
需求二
hive (ruozeg6)> select name,size(work_locations) from hive_array;
OK
ruoze 4
jepson 4
Time taken: 0.081 seconds, Fetched: 2 row(s)
需求三
hive (ruozeg6)> select * from hive_array where array_contains(work_locations,"tianjin");
OK
ruoze ["beijing","shanghai","tianjin","hangzhou"]
Time taken: 0.092 seconds, Fetched: 1 row(s)
数据准备:
数据解读:
[hadoop@hadoop004 data]$ cat hive_map.txt
1,zhangsan,father:xiaoming#mother:xiaohuang#brother:xiaoxu
2,lisi,father:ron,#mother:rebacca#brother:john
第二步:
create table hive_map (
id int,
name string,
members map,
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
MAP KEYS TERMINATED BY ':'
COLLECTION ITEMS TERMINATED BY '#';
hive (ruozeg6)> create table hive_map(
> id int,
> name string,
> members map
> )
> ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
> MAP KEYS TERMINATED BY ':'
> COLLECTION ITEMS TERMINATED BY '#';
FAILED: ParseException line 8:0 missing EOF at 'COLLECTION' near '':''
hive (ruozeg6)> create table hive_map(
> id int,
> name string,
> members map
> )
> ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
> COLLECTION ITEMS TERMINATED BY '#'
> MAP KEYS TERMINATED BY ':';
OK
Time taken: 0.171 seconds
第三步:加载数据进hive_map
hive (ruozeg6)> load data local inpath '/home/hadoop/data/hive_map.txt' overwrite into table hive_map;
Loading data to table ruozeg6.hive_map
Table ruozeg6.hive_map stats: [numFiles=1, numRows=0, totalSize=106, rawDataSize=0]
OK
Time taken: 0.567 seconds
需求一:
hive (ruozeg6)> select id,name,members['father'] from hive_map;
OK
1 zhangsan xiaoming
2 lisi ron
Time taken: 0.215 seconds, Fetched: 2 row(s)
需求二:
hive (ruozeg6)> select map_keys(members) from hive_map;
OK
["father","mother","brother"]
["father","mother","brother"]
["father","mother","brother"]
["father","mother","brother"]
Time taken: 0.069 seconds, Fetched: 4 row(s)
hive (ruozeg6)> select map_values(members) from hive_map;
OK
["xiaoming","xiaohuang","xiaoxu"]
["ron","rebacca","john"]
["meixuefang","guxiangmei","meiguojun"]
["sail","ron","zacker"]
Time taken: 0.092 seconds, Fetched: 4 row(s)
需求三:
hive (ruozeg6)> select size(members) from hive_map;
OK
3
3
3
3
Time taken: 0.069 seconds, Fetched: 4 row(s)
数据准备:
[hadoop@hadoop004 data]$ cat hive_struct.txt
192.168.1.1#zhangsan:25
10.0.0.135#lisi:27
192.168.137.252#sail:24
10.0.0.135#robert:29
2、建表语句
hive (ruozeg6)> create table hive_struct (
> ip string,
> userinfo struct
> )
> ROW FORMAT DELIMITED FIELDS TERMINATED BY '#'
> COLLECTION ITEMS TERMINATED BY ':';
OK
Time taken: 0.504 seconds
3、加载数据并且查询
hive (ruozeg6)> load data local inpath '/home/hadoop/data/hive_struct.txt' into table hive_struct;
Loading data to table ruozeg6.hive_struct
Table ruozeg6.hive_struct stats: [numFiles=1, totalSize=88]
OK
Time taken: 0.358 seconds
hive (ruozeg6)> select userinfo.name,userinfo.age from hive_struct;
OK
zhangsan 25
lisi 27
sail 24
robert 29
Time taken: 0.043 seconds, Fetched: 4 row(s)
1、array_type数组是用work_locations[0]取值
2、map type是用members[key]
3、struct_type是用userinfo.name
这些结构都是行式存储,要转换成列式才能使用,我们只需要把他们清洗出来,做成一张大宽表;肯定是设计一个数据的转换,基于转换的这张表进行查询的