零基础班第十六课 - Hive DML详解

第一章:上次课回顾

第二章:Hive DML语法

第三章:Hive中的SQL语句

第四章:本次课程面试题

第一章:上次课回顾

  • 零基础班第十五课 - Hive DDL详解:
    https://blog.csdn.net/zhikanjiani/article/details/89075266

重点是:

1、Hive的数据库、表的创建、修改、删除相关;
2、创建数据库、表都是可以指定location的,也可以不指定的;
3、default库对应的hdfs路径在哪,自己创建的数据库的路劲在哪?

1、default库对应的hdfs的路径如下:
hive (default)> desc database default;
OK
default Default Hive database   hdfs://localhost:9000/user/hive/warehouse       public ROLE
Time taken: 0.102 seconds, Fetched: 1 row(s)

2、自己创建的ruozeg6数据库的hdfs的路径:
hive (default)> desc database ruozeg6;
OK
ruozeg6         hdfs://hadoop004:9000/user/hive/warehouse/ruozeg6.db    hadoop  USER
Time taken: 0.432 seconds, Fetched: 1 row(s)

3、自己创建的数据库也可以不使用/user/hive/warehouse默认路径,而是自己指定路径,如下:
hive (default)> desc database hive2;
OK
hive2           hdfs://hadoop004:9000/d6/hive/directory hadoop  USER
Time taken: 0.108 seconds, Fetched: 1 row(s)

内部表和外部表的区别一定要搞懂

  • 还简单讲了Hive中使用load加载数据

DML:
在Hive中需要注意的一点:

  • 在关系型数据库中是通过insert的方式写进去的;
  • 但是在大数据场景中,使用insert的场景是不多的;
  • 大部分加载数据都是采用load的方式加载到表中去(把一批文件load到表中去),实际就是把数据加载到hdfs上,因为meta信息已经有了;所以就能直接进行查询。

第二章:Hive DML语法

官网上显示:

DML (load/insert/update/delete/merge, import/export, explain plan)

2.1 :LOAD的用法

语法:

  • LOAD DATA [LOCAL] INPATH ‘filepath’ [OVERWRITE] INTO TABLE tablename [PARTITION]

  • 解释:local 指的是本地路径,有local默认是本地linux,不带local的话它会去hdfs的路径上找;overwrite指的是表内容是否覆盖。

开始进行测试:

1、在本地路径:/home/hadoop/data 下vi一个dept.txt

[hadoop@hadoop004 data]$ pwd
/home/hadoop/data
[hadoop@hadoop004 data]$ cat dept.txt 
10      accouting       newwork
20      restart china
30      sales   japan  

2、 此时在hive中创建一张表:

create table dept(
deptno string,
dname string,
location string
)row format delimited fields terminated by ‘\t’;

  • 此时表创建完成,暂时为空表。

3、使用load加载dept.txt文件内容至dept表
命令:

  • load data local inpath ‘/home/hadoop/data/dept.txt’ overwrite into table dept;
hive> load data local inpath '/home/hadoop/data/dept.txt' overwrite into table dept;
Loading data to table g6.dept
[Warning] could not update stats.
OK
Time taken: 25.649 seconds
hive> select * from dept;
OK
10      accouting       newwork
20      restart china
30      sales   japan
Time taken: 0.545 seconds, Fetched: 3 row(s)

2.2、测试有无overwrite的区别

测试有无overwrite的区别

hive> load data local inpath '/home/hadoop/data/dept.txt'  into table dept;
hive> select * from dept;
OK
10      accouting       newwork
20      restart china
30      sales   japan
10      accouting       newwork
20      restart china
30      sales   japan
Time taken: 0.087 seconds, Fetched: 6 row(s)

官网中对有无overwrite的描述:

  • If the OVERWRITE keyboards is used then the contents of the target table (or partition) will be deleted and replaced by the files referred to by filepath; otherwise the files referred by filepath will be added to the table.

  • 无overwrite是追加,有overwrite是覆盖

2.3、测试有无local的区别

  • 目前我们使用的是local指定到linux本地路径,假设我们不使用local。

1、把data目录下的dept.txt文件上传到hdfs文件系统上:

[hadoop@hadoop004 data]$ hdfs dfs -mkdir -p /hive/dept
[hadoop@hadoop004 data]$ hdfs dfs -put dept.txt /hive/dept/
[hadoop@hadoop004 data]$ hdfs dfs -ls /hive/dept
Found 1 items
-rw-r--r--   1 hadoop supergroup         53 2019-04-18 23:59 /hive/dept/dept.txt

2、把hdfs上的文件加载到dept表中(此处选择的是overwrite)

  • load data inpath ‘/hive/dept/dept.txt’ overwrite into table dept;

3、我们再去hdfs路径上/hive/dept/dept.txt上查看:

[hadoop@hadoop004 data]$ hdfs dfs -ls /hive/dept
19/09/10 07:24:24 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
  • 查看到该文件夹下为空,第2步中的load操作就相当于是把这份数据移走了。

同时需要注意:

  • ‘/hive/data/dept.txt’ 这个hdfs路径可以补全 ==> hdfs://hadoop004:9000/hive/dept/dept.txt,因为我们是在系统里面配置的,所以头部没有 ‘hdfs://hadoop004:9000’ 也能识别。

内部表与外部表区别?
https://blog.csdn.net/zhikanjiani/article/details/94492610

2.4、Hive中insert的使用

insert语法如下:

1、insert语句的底层是要跑MapReduce作业的.
INSERT OVERWRITE LOCAL DIRECTORY '/home/hadoop/tmp/d6/'
row format delimited fields terminated by ','			//输出的结果以逗号为分割
select deptnu,dname from dept;			//跟上的SQL语句

2、在/home/hadoop/tmp/d6目录下,打印输出文件,得到结果
[hadoop@hadoop004 d6]$ pwd
/home/hadoop/tmp/d6
[hadoop@hadoop004 d6]$ ll
total 4
-rw-r--r--. 1 hadoop hadoop 33 Apr 19 00:25 000000_0
[hadoop@hadoop004 d6]$ cat 000000_0 
10,accouting
20,restart
30,sales

3、2的结果就等价于
create table xxx as select deptno,dname from dept;

insert是在hive0.14版本中出现的,语法上是支持的,但是生产上是拒绝使用的。

生产举例:

  • PK哥公司1minute几百G数据,插入会产生很多小文件,需要保证每一次数据处理的幂等性(不管跑多少次都要保证结果为真);insert的前提肯定是没有的数据才需要insert。
    大数据忌讳:像webUI界面一样,点击按钮去跑MapReduce作业,要看数据量以及资源量

  • hive中delete删除数据,首先要去找这个数据在哪再去删除,所以性能是非常低的。

幂等性:

  • 数据丢了每一个批次重跑就行(就是不论运行了多少次,每一次运行的结果都是一样的)
  • 对于一张表来说,我们load一次就够了,load是支持目录的;一个分区就是一个目录,一个分区不会与文件个数有关系,它是到文件夹的,不会关心文件夹下的个数有多少?
  • 只要一load,元数据就会关联上;在Hive中,有数据进来(有可能是使用spark清洗、外部数据进来的)

在这里插入图片描述

图解:

1、源数据是我们要处理的数据也就是source,假设数据已经进来了在hdfs上,由于日志可能是乱七八糟的,所以要对这份数据做一个清洗(ip解析);表创建的时候指定分隔符:假设是"\t",这中间可能就会以逗号分隔开。

2、涉及到ip解析(省份、运营商、地市)<== 肯定要做一个etl

3、etl output出来的文件字段信息必然是和a表一致的,每个字段都要能对应上,etl输出的肯定是存放在hdfs上的;肯定是创建的external表,把hdfs path指向hdfs上的存储

4、a表肯定是要采用列式存储,外部表的典型场景

5、我们要在a表中insert数据,那肯定是源端数据中是没有的,是数据采集端的问题。

web的交互方式遇到的问题:

  • 在页面上写一个按钮,按钮去触发Hive、MapReduce作业(数据多久跑完根本不可控),只能拿SQL的语法来套;insert、update、delete都是在大数据中禁用的。

  • 假设我们要统计每个省份的topN,我们肯定要把它的结果Insert到B表中去。

  • 离线的作业跑20个小时都正常,Pk哥公司一个作业跑2分钟;要想跑的快,加资源,一个作业动辄就上T的内存。

  • 删除、更新都要到文件中去找出这个数据在哪,所以这个性能是很差的。

Hadoop体系:Sqoop

Spark体系:Spark SQL

Linux中的Hive体系

2.5、Hive在生产上的使用

1、hive -e

1、hive -e "select * from dept;"				联想到脚本

2、vi a.sh
#!/bin/bash
hive -e "use g6;select * from dept"  选择数据库,再把需要统计的东西写进Hive -e

3、执行这个脚本
./a.sh 

2、hive -f

1、编辑一个名称为test.sql的脚本文件
vi test.sql
如下两行是脚本文件中的内容:
use g6;
select * from dept limit 3;		这是一个脚本

2、自己找一个目录编辑即可
[hadoop@hadoop004 d6]$ ll
total 12
-rw-r--r--. 1 hadoop hadoop 33 Apr 19 00:25 000000_0
-rwxrwxr-x. 1 hadoop hadoop 49 Apr 19 00:47 a.sh
-rw-rw-r--. 1 hadoop hadoop 35 Apr 19 00:54 test.sql
[hadoop@hadoop004 d6]$ pwd
/home/hadoop/tmp/d6

3、找到路径,开始执行test.sql
[hadoop@hadoop004 d6]$ hive -f test.sql

Logging initialized using configuration in jar:file:/home/hadoop/app/hive-1.1.0-cdh5.7.0/lib/hive-common-1.1.0-cdh5.7.0.jar!/hive-log4j.properties
OK
Time taken: 0.699 seconds
OK
10      accouting       newwork
20      restart china
30      sales   japan
Time taken: 0.955 seconds, Fetched: 3 row(s)

hive界面下的清屏操作:!clear; + 回车

第三章:Hive中的SQL语法

  • 在Hive中,where、>、<、=、limit、between也是支持的between XXX and XXX、

  • 数据使用的是emp表

1、select * from emp limit 5;

  • 输出emp表中的前5行

2、select * from emp where sal between 800 and 1500;

  • 输出emp表中满足(金额在800到1500)这个区间的所有信息

3、select * from emp where Ename in (‘SMITH’,‘WARD’);

  • 我们在3中测试的时候使用了where Ename in,使用desc emp; 查看表结构信息字段名称是ename,测试的时候发现它自动的对字段名称的大小进行了转换。

验证这一猜想:

大小写做了转换去元数据中查看,进入到mysql,columns_v2查看表字段都是小写;
1、mysql -uroot -p 进入数据库

2、use ruoze_g6;这个创建的数据库:问?还记得这个数据库是在哪儿创建的么,路径:/home/hadoop/app/hive/conf 下的hive-site.xml文件进行编辑。

3、show tables;

4、select * from tbls \G; 查看所有表格信息,根据表的id去找字段

在这里插入图片描述
5、select * from COLUMNS_V2 limit 5; 所有的列的表。判定肯定把Ename转换为小写了;
在这里插入图片描述

如果列名错误的话他会提示找不到字段报错。具体展示如下几张图:

6、select ename from emp where sal is null;

在这里插入图片描述

3.1 最基础的SQL进行需求分析

聚合函数:max min sum count avg 多进一出

需求一:统计这张表中最高工资、最低工资、工资总和、工资数、平均工资

  • select max(sal),min(sal),sum(sal),count(sal),avg(sal) from emp;

  • 解析:该SQL会去跑MapReduce.
    在这里插入图片描述

需求二:求每个部门的平均工资

拿到每个部门的数据,在此基础上求平均工资:

  • select deptno,avg(sal) from emp group by deptno;

注意点:出现在select中的字段要么出现在group by中,要么出现在聚合函数中;
groupby前后只能对应一个字段。

在这里插入图片描述
错误点:

hive (ruozeg6)> select ename,deptno,avg(sal) from emp group by deptno;
FAILED: SemanticException [Error 10025]: Line 1:7 Expression not in GROUP BY key 'ename'

需求三:每个部门下平均薪资>2000

  • select deptno,avg(sal) as avg_sal from emp group by deptno where avg_sal > 1000;

注意:此段是错误的,使用group by配合having使用,正确的SQL如下:

  • select deptno,avg(sal) as avg_sal from emp group by deptno having avg_sal > 1000;

扩充:groupBy能不能和where搭配使用?

需求四:薪资在某个区间输出高或低

  • case when then 在报表系统中比较常用
select ename,sal,
case
when sal >1 and sal <1000 then 'lower'					//工资在(1,1000)中,你的工资太低了
when sal >=1000 and sal <2000 then 'middle'			//工资在[1000,2000)中,你的工资中等
when sal >=2000 and sal <7000 then 'high'					//工资在[2000,7000)中,你的工资很高了
else 'highest' end 														//其余的是最高的,然后结束
from emp;

了解下用法:它是不走Map Reduce的

在这里插入图片描述

3.2 常用内置、外置函数

1、函数 built-in 内置

2、upper lower(外置函数)也叫自定义函数

3、如何知道Hive中内置的函数

  • operators and UDFs(user-defined functions)
  • 网址:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

4、我们下次要学东西不要直接百度,直接去官网上查看,官网上查看内置函数:最准确的应该是在源码中的体现,源码中怎么找内置函数:

5、在Hive客户端上展示所有的函数

1、Hive下展示所有函数:
hive > show functions  
		
2、查看abs函数的信息:					
hive (ruozeg6)> desc function abs;				//查看abs函数的信息。
OK
abs(x) - returns the absolute value of x
Time taken: 0.144 seconds, Fetched: 1 row(s)

3、查看abs函数的详细信息,包括案例
hive (ruozeg6)> desc function extended abs;				查看ABS函数的详细信息,包括有案例。
OK
abs(x) - returns the absolute value of x
Example:
  > SELECT abs(0) FROM src LIMIT 1;
  0
  > SELECT abs(-5) FROM src LIMIT 1;
  5
Time taken: 0.068 seconds, Fetched: 6 row(s)

绝对值函数:

hive> select abs(-20) from math;
OK
20
Time taken: 2.171 seconds, Fetched: 1 row(s)
hive> desc function extended abs;
OK
abs(x) - returns the absolute value of x
Example:
  > SELECT abs(0) FROM src LIMIT 1;
  0
  > SELECT abs(-5) FROM src LIMIT 1;
  5
Time taken: 0.019 seconds, Fetched: 6 row(s)

3.3、使用内置函数进行大小写、时间函数的转换

  • select ename,lower(ename) from emp;

3.3.1、第一种:时间函数

1、获取当前时间精确到天数

  • select current_date from emp;
hive (ruozeg6)> select current_date from dual;
OK
2019-09-11
Time taken: 0.072 seconds, Fetched: 1 row(s)

2、获取到当前时间精确到秒

  • select current_timestamp from dual;
hive (ruozeg6)> select current_timestamp from dual;
OK
2019-09-11 20:55:35.867

3、在工作中经常用的是一个时间戳,日志进来很多都是这种格式。

  • select unix_timestamp() from dual;
hive (ruozeg6)> select unix_timestamp() from dual;
OK
1568206640

百度时间戳转换:2019-09-11 20:57:20

日志进来的不同时间格式:

1、将时间转换为时间戳形式:

  • select unix_timestamp(“2019-04-19 05:49:26”) from dual;
hive (ruozeg6)> select unix_timestamp("2019-04-19 05:49:26") from dual;
OK
1555624166

3、另外一种时间格式(yyyyMMddHHmmss)转换为时间戳:

  • select unix_timestamp(“20190419054926”,“yyyyMMddHHmmss”) from dual;
hive (ruozeg6)> select unix_timestamp("20190419054926","yyyyMMddHHmmss") from dual;
OK
1555624166

4、to_date函数的使用:

  • select to_date(“2019-04-19 05:49:26”) from dual;
hive (ruozeg6)> select to_date("2019-04-19 05:49:26") from dual;
OK
2019-04-19
  • 返回值是data类型
    在这里插入图片描述

小结:

我们为什么要转换成字符串类型呢,我们按照天、小时的话直接加一个分区,里面的东西就可以直接按照分区进行过滤。

5、分别获取到"2019-04-19 05:49:26"这个信息中的年、月、日、时、分、秒

  • select month(“2019-04-19 05:49:26”)from dual;
  • 直接替换year–>month–>day–>hour–>minute–>second
hive (ruozeg6)> select year("2019-04-19 05:49:26") from dual;
OK
2019
Time taken: 0.081 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select month("2019-04-19 05:49:26") from dual;
OK
4
Time taken: 0.078 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select day("2019-04-19 05:49:26") from dual;
OK
19
Time taken: 0.084 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select hour("2019-04-19 05:49:26") from dual;
OK
5
Time taken: 0.06 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select minute("2019-04-19 05:49:26") from dual;
OK
49
Time taken: 0.072 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select second("2019-04-19 05:49:26") from dual;
OK
26
Time taken: 0.062 seconds, Fetched: 1 row(s)

6、完成日期的加减(date add)函数:

  • 在此基础上使用减法也是一样
  • select date_add(“2019-04-19 05:49:26”,10) from dual;
hive (ruozeg6)> select date_add("2019-04-19 05:49:26",10) from dual;
OK
2019-04-29
Time taken: 0.137 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select date_add("2019-04-19 05:49:26",-10) from dual;
OK
2019-04-09
Time taken: 0.078 seconds, Fetched: 1 row(s)

3.3.2、第二种:Mathematical Functions

1、round函数

  • 作用:四舍五入
hive (ruozeg6)> select round(5.6) from dual;
OK
6.0
Time taken: 0.084 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select round(5.4) from dual;
OK
5.0
Time taken: 0.06 seconds, Fetched: 1 row(s)

2、ceil函数

  • ceil(x) - Find the smallest integer not smaller than x
hive (ruozeg6)> select ceil(5.6) from dual;
OK
6
Time taken: 0.069 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select ceil(5.4) from dual;
OK
6
Time taken: 0.062 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select ceil(6.1) from dual;
OK
7

3、floor函数

  • floor(x) - Find the largest integer not greater than x
hive (ruozeg6)> select floor(6.1) from dual;
OK
6
Time taken: 0.056 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select floor(6.6) from dual;
OK
6
Time taken: 0.058 seconds, Fetched: 1 row(s)

4、substr函数

  • 作用:截取字符串

1、位置从第一个字符a开始,从第二个字符b开始往后截取。

  • select substr(“abcdefg”,2) from dual;

2、从第二个字符b开始向后截取3位

  • select substr(“abcdefg”,2,3) from emp;
hive (ruozeg6)> select substr("abcdefg",2) from dual; 
OK
bcdefg
Time taken: 0.08 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select substr("abcdefg",2,3) from dual; 
OK
bcd
Time taken: 0.092 seconds, Fetched: 1 row(s)

5、concat函数的用法:
1、把如下字符合在一起

  • select concat(“ab”,“cd”,“fg”) from dual;
  • 输出结果:abcdfg

6、把字符分割开:

  • select concat_ws("---------",“tree”,“17”) from dual;
1、查看concat_ws函数定义:
concat_ws(separator, [string | array(string)]+) - returns the concatenation of the strings separated by the separator.

2、测试
hive (ruozeg6)> select concat_ws("----","tree","17") from dual;
OK
tree----17
Time taken: 0.189 seconds, Fetched: 1 row(s)

7、Split函数

场景描述:我们在浏览手机新闻的时候,发送给客户端的是一条ip+port的信息。

  • desc function extended split;
  • select split(“192.168.1.1:8020,”"\.") from emp;
hive (ruozeg6)> select split("192.168.199.151:8020",".") from dual;
OK
["","","","","","","","","","","","","","","","","","","","",""]
Time taken: 0.062 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select split("192.168.199.151:8020","\\.") from dual;
OK
["192","168","199","151:8020"]
Time taken: 0.046 seconds, Fetched: 1 row(s)
hive (ruozeg6)> select split("192.168.199.151:8020","\\.") from dual;
OK
["192","168","199","151:8020"]
Time taken: 0.07 seconds, Fetched: 1 row(s)

特殊字符要加\进行转义。
问题:转义字符是个什么东西?

3.4、Hive完成Wordcount统计分析

第一步:创建Hive表,准备数据加载进去

  • create table d6_wc(sentence string); 创建hive表

  • load data local inpath ‘/home/hadoop/data/wc.txt’ into table d6_wc; 把wc.txt文件加载入表。

1、select split(sentence,"\t")from d6_wc;

  • split(str, regex) - Splits str around occurances that match regex

2、select explode(split(sentence,"\t")) from d6_wc;

  • explode:分割数组中的元素将其转换成多行
hive (ruozeg6)> select split(sentence,"\t") from d6_wc;
OK
["ruoze","ruoze","ruoze"]
["jepson","jepson"]
["john"]
Time taken: 0.077 seconds, Fetched: 3 row(s)
hive (ruozeg6)> select explode(split(sentence,"\t")) from d6_wc;
OK
ruoze
ruoze
ruoze
jepson
jepson
john
Time taken: 0.069 seconds, Fetched: 6 row(s)

3、SQL统计这些词出现的个数

hive完成wc,split完成分割、explode完成行转列、SQL统计

select word,count(1) as c
from
(select	explode(split(sentence,"\t"))	as	word	from		d6_wc)  as t  
group by word			//以word进行groupby
order by c desc;		//排序
  • Total job = 2,没有order by的话只有一个job

  • 必然是两个mapreduce作业,groupBy和orderBy没办法并行执行,order by的执行依赖于group by.

  • 生成几个job就对应几个MapReduce作业

结果显示如下:
在这里插入图片描述

第四章:本次课程面试题

面试题1:Hive中是否支持insert?

  • 支持,从0.14版本开始起Hive是支持insert的,但是生产上是拒绝使用insert的,insert数据就肯定意味着的是那一分钟的数据丢了,数据丢了是前端采集的事情;我们必须要保证每一批数据处理的幂等性(数据不管跑多少次,都要保证每一次的数据都是正确的)。

面试题2:在hive中null、0、" "、’ '的区别,如何处理?

面试题3:hive的行转列、列转行

作业1:求每个部门、工作岗位的最高薪资

作业2:desc function extended abs; 中出现的案例是怎么来的呢?

作业3:Hive求每个月月底的一天?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值