Hive_DML-函数-分区表

一、DML : Data Manipulation Language

 

1.加载数据到表:

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

---LOCAL本地的意思,这里是指linux系统,如果没有LOCAL,就指hdfs

 

根据dept.txt

a. 创建表ruoze_dept

create table ruoze_dept(

deptno int,

dname string,

loc string

)ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

 

b.导入数据

LOAD DATA LOCAL INPATH '/home/hadoop/data/dept.txt' INTO TABLE ruoze_dept; #这里没加overwrite

load data local inpath '/home/hadoop/data/dept.txt' overwrite into table ruoze_dept; #这里加了overwrite

 

c.查询一下数据

 

 

以hdfs的方式load

先把数据put 到hdfs上,hadoop fs -put ‘/home/hadoop/data/dept.txt’  /data

跟着LOAD DATA INPATH '/data/dept.txt' INTO TABLE ruoze_dept; #因为是用hdfs,所以不需要添加local关键字。

最后可以用select * from ruoze_dept; 查询一下。

注意:用hdfs的方式,load一次后,如果再load一次相同的文件时就会报错

因为是用内部表,hdfs上的dept.txt移动到目标地方,相同于mv了,所以hdfs就已经没有dept.txt这个文件了.

 

2.以SQL插入数据

Standard syntax:

INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;

INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;

 

INSERT OVERWRITE TABLE ruoze_emp_test select empno,ename from ruoze_emp;

# 这个语句中,select 后面的字段个数跟ruoze_emp_test的字段个数不一样。

 

INSERT OVERWRITE TABLE ruoze_emp_test

select empno,job,ename,mgr,hiredate,sal,comm,deptno from ruoze_emp;

#这个语句中,select后面的字段位置错位了,执行时是可以运行的,但是结果是不对的,所以要注意。

 

另:要注意不要用下面这种插入数据的方式,因为大量的数据,不可能一条一条插入

INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES values_row [, values_row ...] ;

同理,下面update和delete的方式也不要用。

UPDATE tablename SET column = value [, column = value ...] [WHERE expression];

DELETE FROM tablename [WHERE expression];

 

 

3.导出数据

INSERT OVERWRITE LOCAL DIRECTORY '/tmp/ruoze'

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'

SELECT empno,ename FROM ruoze_emp; #跟前面的一样,有local关键字表示写入本地(即linux),不添加local关键字表示写入hdfs

可以进去/tmp/ruoze这个路径看看是否有数据

Hive_DML-函数-分区表_第1张图片

 

 

二.DML的查询相关的内容以及函数

      

我们说 Hive是构建在Hadoop之上的数据仓库

那么,sql ==> Hive ==> MapReduce,(sql提交到hive后,转化成MP执行的),那么好像下面的有转化成MP作业吗?是没有的。这个简单的是没有的。

 

1.聚合函数: max  min  sum  avg  count

对于聚合函数的语句,是会跑MP作业的。

 

2.分组函数,出现在select中的字段,要么出现在group by子句中,要么出现在聚合函数中,叫叫做分组函数。

       求部门的平均工资

       求每个部门、工作岗位的最高工资

       求每个部门的平均薪水大于2000的部门

       select deptno,avg(sal) from ruoze_emp group by deptno having avg(sal)>2000;

       #要注意having 要用在group by 后面。

      

3.case when then 类似于 if-else      

 

select ename, sal,

case

when sal>1 and sal<=1000 then 'LOWER'

when sal>1000 and sal<=2000 then 'MIDDLE'

when sal>2000 and sal<=4000 then 'HIGH'

ELSE 'HIGHEST' end

from ruoze_emp;

 

4.union和union all

select count(1) from ruoze_emp where deptno=10

union all

select count(1) from ruoze_emp where deptno=20;

 

union可以用在数据倾斜,比如a1是不倾斜的,a2表是倾斜的,把正确的捞出来,不正确的也捞出来,最后union

a = a1 union all a2

 

5.那这么多内置函数,怎么查出来hive所支持的内置函数呢?

可以用desc functions,如果是具体的某一函数比如upper的用法,可以用

desc function extended upper;来查询一下。

但有些内置函数用desc function是查不出来,比如cast,

cast(value as TYPE) 如果转换失败,返回值就是null。

另外截取字符串substring、拼接字符串concat、concat_wc、切割函数split也是常用的

 

explode行转列函数的使用,现在看看下面这个内容,假如有3个学生,有对应的选修的科目,但是他们选的科目是一个数组

1,doudou,化学:物理:数学:语文

2,dasheng,化学:数学:生物:生理:卫生

3,rachel,化学:语文:英语:体育:生物

 

a.根据上面的信息,在 '/home/hadoop/data/' 新建student.txt

b.建表

create table ruoze_student(

id int,

name string,

subjects array

)row format delimited fields terminated by ','

COLLECTION ITEMS TERMINATED BY ':';  #集合里面的分隔符是用 : 号

 

c.导入(上传)数据

load data local inpath '/home/hadoop/data/student.txt' into table ruoze_student;

 

d.查询一下,select * from ruoze_student; # 有3列,注意第三列是一个数组集合

Hive_DML-函数-分区表_第2张图片

 

e.用行转列函数explode

select distinct s.sub from (select explode(subjects) sub from ruoze_student) s

Hive_DML-函数-分区表_第3张图片

意思是先select explode(subjects) sub from ruoze_student查出来,再distinct去重。

 

6.需求:使用hive完成wordcount (hive和spark的wordcount统计在面试时会经常考)

 

a.create table ruoze_wc(

sentence string

);

 

b.在/home/hadoop/data建立wc.txt

hello,world,welcome

hello,world

hello,welcome

 

c.导入数据到hive

load data local inpath ‘/home/hadoop/data/wc.txt’ overwrite into table ruoze_wc ;

 

d.执行sql

select word, count(1) as c

from

(

select explode(split(sentence,",")) as word from ruoze_wc

) t

group by word

order by c desc;

split是分割数组,explode是行转列,count(1)作统计。见下图,已经完成wordcount。

 

 

三、分区表

1、分区表简介和一级分区

除了内部表、外部表,还有分区表。

什么是分区表呢?分区表:一个表按照某个字段进行分区

那分区的意义何在呢?举个例子

access.log –--是数据量很大的一个日志

要求查该日子startime>201810212200 and starttime < 201810212359

这样查性能很低。

所以需要做分区:

比如要查20181021这一天的数据,就不需要查其它日期的数据

/user/hive/warehouse/access/d=20181021

 

先创建分区表

create table order_partition(

orderNumber string,

event_time string

)PARTITIONED BY(event_month string)

row format delimited fields terminated by '\t'; #创建分区表时,是需要添加关键字partitioned

导入数据

load data local inpath '/home/hadoop/data/order.txt' into table order_partition PARTITION (event_month='2014-05'); # 平常普通表不用PARTITION的,但分区表要加PARTITION

 

注意:如果load数据时有字符集的问题,可以按照下面的方法修改

use ruoze_d5;

alter table PARTITIONS convert to character set latin1;

alter table PARTITION_KEYS convert to character set latin1;

Hive_DML-函数-分区表_第4张图片

 

然后可以去hdfs上看看(在hdfs上分区表也是一个目录,一个分区对应一个目录),目录的名字有点特殊的,它是采用

分区字段=分区值所以以后看到这种结构,就是分区表

hadoop fs -ls /user/hive/warehouse/d5_hive.db/order_partition

Hive_DML-函数-分区表_第5张图片

既然我们知道规则和道理了,那我们再建一个分区表event_month=2014-06,

hadoop fs -mkdir  /user/hive/warehouse/d5_hive.db/order_partition/event_month=2014-06

将数据put到hdfs的分区上

hadoop fs -put order.txt

 /user/hive/warehouse/d5_hive.db/order_partition/event_month=2014-06

查一下是否有数据 select * from order_partition where event_month='2014-06';

结果是没有数据。原因是元数据里面没有数据。

我们可以刷新一下分区,用msck repair table order_partition;

现在再来查询一下,分区event_month='2014-06'已经有数据了

Hive_DML-函数-分区表_第6张图片

因为这个命令会把 2014-06的信息从MySQL表里面刷新,从而可以再Hive上查询表可以查询的到信息同步过来了。但有一个致命的缺点,它会把刷新所有MySQL表里面的信息,性能会非常低。所以杜绝用msck repair table order_partition;

可以用alter table …add …解决,在生产上用这种刷新的方式。现在来试试:

我们创建一个新的分区表,把本地的数据放到hdfs分区表event_month=2014-07的上面。

新创建一个分区表:

hadoop fs -mkdir  /user/hive/warehouse/d5_hive.db/order_partition/event_month=2014-07

将数据put到hdfs的分区上:

hadoop fs -put order.txt

/user/hive/warehouse/d5_hive.db/order_partition/event_month=2014-07/

现在查分区表是没有的,就用

alter table order_partition add if not exists partition(event_month='2014-07');

现在查一下有数据了。

Hive_DML-函数-分区表_第7张图片

 

查询一个表有多少个分区

用:show partitions order_partition;

 

2.多级分区

在hive或spark SQL生产上,我们一般是多级分区用得比较多。

再创建一个分区

create table order_mulit_partition(

orderNumber string,

event_time string

)PARTITIONED BY(event_month string, step string)

row format delimited fields terminated by '\t';

#这里 (event_month string, step string),如果有一个字段是一级分区,有多个字段的是多级分区

 

加载(导入)数据

load data local inpath '/home/hadoop/data/order.txt' into table order_mulit_partition PARTITION (event_month='2014-05',step='1');

查询一下

Hive_DML-函数-分区表_第8张图片

再在hdfs上查看一下

Hive_DML-函数-分区表_第9张图片

 

前面所讲的单级分区/多级分区 ==>统称为 静态分区

什么叫静态分区?即导数据时就是把分区字段写全了。

 

3.动态分区

 

CREATE TABLE `ruoze_emp_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';

# 分区的字段是不能出现在表字段里面的,所以deptno是不能出现在create的()里面的。

 

现在有一个需求,请按照ruoze_emp的这张表的部门编号作为分区字段将ruoze_emp这张表里面的数据写到分区表里面。

按之前的方法是这样:

insert into table ruoze_emp_partition PARTITION(deptno=10)

select empno,ename,job,mgr,hiredate,sal,comm from ruoze_emp where deptno=10;

 

假设:有1000个deptno,用上面的方法插入的话,那就累死人了。这就是静态分区的弊端,这时可以用动态分区完成,那如何用动态分区去完成?

分区字段里面直接写字段,而不要赋值,另外,还要把分区字段写在select字段的最后面,如果分区字段有两个以上,那select后面的字段也同样要对应上

insert overwrite table ruoze_emp_partition PARTITION(deptno)

select empno,ename,job,mgr,hiredate,sal,comm,deptno from ruoze_emp;

执行后,如果提示上面截图错误提示,是因为默认是严格模式,是无法使用动态赋值的,需要关掉这个值

set hive.exec.dynamic.partition.mode=nonstrict

现在重新执行insert语句

查询一下,select * from ruoze_emp_partition; 已经有数据了。

Hive_DML-函数-分区表_第10张图片

去hdfs上查看一下,也已经有数据了

Hive_DML-函数-分区表_第11张图片

所以,如果分区字段的值不固定的话,可以用这个动态分区的方法了。

 

 

你可能感兴趣的:(Hive)