[老實(shí)李]HIVE學(xué)習(xí)筆記

一、HIVE簡(jiǎn)介

Hive是一種建立在Hadoop文件系統(tǒng)上的數(shù)據(jù)倉(cāng)庫(kù)架構(gòu),并對(duì)存儲(chǔ)在HDFS中的數(shù)據(jù)進(jìn)行分析和管理;它可以將結(jié)構(gòu)化的數(shù)據(jù)文件映射為一張數(shù)據(jù)庫(kù)表,并提供完整的 SQL 查詢功能,可以將 SQL 語(yǔ)句轉(zhuǎn)換為 MapReduce 任務(wù)進(jìn)行運(yùn)行,通過(guò)自己的 SQL 去 查詢分析需要的內(nèi)容,這套 SQL 簡(jiǎn)稱 Hive SQL(HQL),使不熟悉 MapReduce 的用戶也能很方便地利用 SQL 語(yǔ)言對(duì)數(shù)據(jù)進(jìn)行查詢、匯總、分析。同時(shí),這個(gè)語(yǔ)言也允許熟悉 MapReduce 開(kāi)發(fā)者們開(kāi)發(fā)自定義的mappers和reducers來(lái)處理內(nèi)建的mappers和reducers無(wú)法完成的復(fù)雜的分析工作。Hive還允許用戶編寫自己定義的函數(shù)UDF,用來(lái)在查詢中使用。Hive中有3種UDF:User Defined Functions(UDF)、User Defined Aggregation Functions(UDAF)、User Defined Table Generating Functions(UDTF)。也就是說(shuō)對(duì)存儲(chǔ)在HDFS中的數(shù)據(jù)進(jìn)行分析和管理,我們不想使用手工,我們建立一個(gè)工具吧,那么這個(gè)工具就可以是hive。

二、簡(jiǎn)單的命令

//展示方法名列表
show functions;
//簡(jiǎn)單方法的解釋
desc function split;

image.png

//解釋方法名并且舉個(gè)例子
desc function extended split;

image.png

//查找sp開(kāi)頭的方法名
show functions like 'sp.*';

image.png

三、分區(qū)和分桶

1.分區(qū)

(1)什么是分區(qū)?
分區(qū)其實(shí)就是再HDFS上存儲(chǔ)的時(shí)候分了一個(gè)相應(yīng)的分區(qū)文件夾,比如你的一個(gè)表 partition_test,然后根據(jù)日期分區(qū)的話,最后HDFS上的就是類似這樣的結(jié)構(gòu)
/user/hive/warehouse/partition_test/stat_date=2015-01-18/province=beijing----顯示剛剛創(chuàng)建的分區(qū)

(2)內(nèi)部表和外部表有什么區(qū)別?
1.內(nèi)部表刪除的時(shí)候會(huì)將表的數(shù)據(jù)和元數(shù)據(jù)信息全部刪除,而外部表僅僅刪除外部表的元數(shù)據(jù),數(shù)據(jù)是不會(huì)刪除的。

  1. 內(nèi)部表在load data的時(shí)候會(huì)將數(shù)據(jù)轉(zhuǎn)移。也就是說(shuō) load data inpath '/input/edata' into table et; 這句話會(huì)把HDFS上的/input/edata文件移動(dòng)到表et的location下面。而外部表不會(huì)。
    3.內(nèi)部表和外部表都會(huì)在 /user/hive/warehouse/新建一個(gè)表的目錄(如果不指定location的話)

(3)內(nèi)部分區(qū)表和外部分區(qū)表
創(chuàng)建一個(gè)簡(jiǎn)單的內(nèi)部分區(qū)表

create table partition_internal(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

PARTITIONED BY(province STRING,city STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';

//為內(nèi)部分區(qū)表指定分區(qū)
ALTER TABLE partition_internal ADD PARTITION (province='henan',city='zhengzhou');
//加載數(shù)據(jù)到內(nèi)部分區(qū)表 這個(gè)時(shí)候會(huì)移動(dòng)數(shù)據(jù)
LOAD DATA INPATH '/user/hive/external01' INTO TABLE partition_internal PARTITION(province='henan',city='zhengzhou');
創(chuàng)建外部分區(qū)表

create  external table partition_external(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

PARTITIONED BY(province STRING,city STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';
create  external table partition_external(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t'

LOCATION '/user/hive/external02';

為外部分區(qū)表添加分區(qū)
ALTER TABLE partition_external ADD PARTITION (province='shanxi',city='xian') LOCATION '/user/hive/external02';

//查看分區(qū)
show partitions partition_external;

//刪除分區(qū)
ALTER TABLE student_partition_external DROP PARTITION(province='guangzhou',city='shenzhen');

//向多個(gè)分區(qū)插入數(shù)據(jù),命令如下。
from partition_test_input

insert overwrite table partition_test partition(stat_date='2015-01-18',province='jiangsu') select member_id,name from partition_test_input where stat_date='2015-01-18' and province='jiangsu'

insert overwrite table partition_test partition(stat_date='2015-01-28',province='sichuan') select member_id,name from partition_test_input where stat_date='2015-01-28' and province='sichuan'

insert overwrite table partition_test partition(stat_date='2015-01-28',province='beijing') select member_id,name from partition_test_input where stat_date='2015-01-28' and province='beijing';

(4)動(dòng)態(tài)分區(qū)
按照上面的方法向分區(qū)表中插入數(shù)據(jù),如果數(shù)據(jù)源很大,針對(duì)一個(gè)分區(qū)就要寫一個(gè) insert ,非常麻煩。使用動(dòng)態(tài)分區(qū)可以很好地解決上述問(wèn)題。動(dòng)態(tài)分區(qū)可以根據(jù)查詢得到的數(shù)據(jù)自動(dòng)匹配到相應(yīng)的分區(qū)中去。

1、啟動(dòng)動(dòng)態(tài)分區(qū)功能(默認(rèn)沒(méi)有啟動(dòng))
set hive.exec.dynamic.partition = true;

2、設(shè)置所有分區(qū)都是動(dòng)態(tài)的
set hive.exec.dynamic.partition.mode=nostrict;

3、準(zhǔn)備兩個(gè)表:一個(gè)普通外部表student_external01,一個(gè)分區(qū)外部表student02
而且要保證分區(qū)表結(jié)構(gòu)student02和student_external01一致
我們以student_external01表為例,但是少兩個(gè)分區(qū)字段,所以我們?cè)僭黾觾蓚€(gè)字段。
ALTER TABLE student_external01 ADD COLUMNS(province STRING,city STRING);

4、先往外部表student_external01中加載數(shù)據(jù)(實(shí)際上現(xiàn)在外部表student_external01中已經(jīng)有數(shù)據(jù)了,因?yàn)閯?chuàng)建該表時(shí)指定了location)
LOAD DATA INPATH '/user/hive/external02/student.txt' INTO TABLE student_external01;

5、利用動(dòng)態(tài)分區(qū)向表中插入數(shù)據(jù)
//先創(chuàng)建分區(qū)外部表student02

create  external table student02(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

PARTITIONED BY(province STRING,city STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';

//利用動(dòng)態(tài)分區(qū)向表中插入數(shù)據(jù)
INSERT OVERWRITE TABLE student02 PARTITION(province,city) SELECT * FROM student_external01 ;
然后數(shù)據(jù)就會(huì)動(dòng)態(tài)分區(qū),把對(duì)應(yīng)的數(shù)據(jù)放到對(duì)應(yīng)的分區(qū)下。

image.png

2.桶操作

Hive 中 table 可以拆分成 Partition table 和 桶(BUCKET),分區(qū)提供了一個(gè)隔離數(shù)據(jù)和優(yōu)化查詢的便利方式,不過(guò)并非所有的數(shù)據(jù)都可形成合理的分區(qū),尤其是需要確定合適大小的分區(qū)劃分方式,(不合理的數(shù)據(jù)分區(qū)劃分方式可能導(dǎo)致有的分區(qū)數(shù)據(jù)過(guò)多,而某些分區(qū)沒(méi)有什么數(shù)據(jù)的尷尬情況)分桶是將數(shù)據(jù)集分解為更容易管理的若干部分的另一種技術(shù)。

數(shù)據(jù)分桶的原理: 跟MR中的HashPartitioner的原理一模一樣, 按照分桶字段的hash值去模除以分桶的個(gè)數(shù)

和分區(qū)的區(qū)別:分桶中的字段是原始數(shù)據(jù)中存在的,而分區(qū)字段在原始文件中并不存在。比如我們上面的那個(gè)分區(qū)province和city字段就是不在student02中的(如果指定了分區(qū)并且表的字段中還包含這兩個(gè)字段的話,hive會(huì)報(bào)錯(cuò)的)

1、開(kāi)啟分桶功能

set hive.enforce.bucketing=true;

2、創(chuàng)建桶表

CREATE TABLE IF NOT EXISTS bucket_table(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

CLUSTERED BY(id) INTO 3 BUCKETS

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';

3、插入數(shù)據(jù)到桶表中
INSERT OVERWRITE TABLE bucket_table SELECT id,name,age FROM student_external01;

二.HIVE復(fù)合類型

hive提供了復(fù)合數(shù)據(jù)類型:

1.Structs: structs內(nèi)部的數(shù)據(jù)可以通過(guò)DOT(.)來(lái)存取。例如,表中一列c的類型為STRUCT{a INT; b INT},我們可以通過(guò)c.a來(lái)訪問(wèn)域a。

  1. 建表
hive> create table student_test(id INT, info struct< name:STRING, age:INT>)

> ROW FORMAT DELIMITED FIELDS TERMINATED BY ','

> COLLECTION ITEMS TERMINATED BY ':';

'FIELDS TERMINATED BY' :字段與字段之間的分隔符。'COLLECTION ITEMS TERMINATED BY' :一個(gè)字段各個(gè)item的分隔符。

  1. 導(dǎo)入數(shù)據(jù)(注意最后不要帶空格不然識(shí)別就是NULL)
$ cat test5.txt

1,zhou:30

2,yan:30

3,chen:20

4,li:80

hive> LOAD DATA LOCAL INPATH '/home/hadoop/djt/test5.txt' INTO TABLE student_test;

  1. 查詢數(shù)據(jù)

hive> select info.age from student_test;

2.Map(K-V對(duì)):訪問(wèn)指定域可以通過(guò)["指定域名稱"]進(jìn)行。例如,一個(gè)Map M包含了一個(gè)group-》gid的kv對(duì),gid的值可以通過(guò)M['group']來(lái)獲取。

  1. 建表
hive> create table employee(id string, perf map< string, int>)

 ROW FORMAT DELIMITED

 FIELDS TERMINATED BY '\t'

COLLECTION ITEMS TERMINATED BY ','

MAP KEYS TERMINATED BY ':';

‘MAP KEYS TERMINATED BY’ :key value分隔符
  1. 導(dǎo)入數(shù)據(jù)
$ cat test7.txt

1 job:80,team:60,person:70

2 job:60,team:80

3 job:90,team:70,person:100

hive> LOAD DATA LOCAL INPATH '/home/work/data/test7.txt' INTO TABLE employee;

  1. 查詢

hive> select perf['person'] from employee;

3)Array:array中的數(shù)據(jù)為相同類型。例如,假如array A中元素['a','b','c'],則A[1]的值為'b'

3.Array使用

  1. 建表
hive> create table class_test(name string, student_id_list array< INT>)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY ','

COLLECTION ITEMS TERMINATED BY ':';
  1. 導(dǎo)入數(shù)據(jù)
$ cat test6.txt

034,1:2:3:4

035,5:6

036,7:8:9:10

hive> LOAD DATA LOCAL INPATH '/home/work/data/test6.txt' INTO TABLE class_test ;

  1. 查詢

hive> select student_id_list[3] from class_test;

三、HIVE的join用法

https://blog.csdn.net/shenxiaoming77/article/details/49489713

四、HIVE的數(shù)據(jù)刪除

1.刪除指定行

image.png

insert overwrite table A select id,name from A where id !=2;

2.刪除表中所有數(shù)據(jù)
truncate table table_name;

五、HIVE數(shù)據(jù)分析結(jié)果的保存

https://blog.csdn.net/u010159842/article/details/70193687

六、hive中order by,sort by, distribute by, cluster by作用以及用法

orderby 就一個(gè)reduce, sortby是指定幾個(gè)reduce就是幾個(gè)reduce進(jìn)行排序,但是并不能保證所有的數(shù)據(jù)都是有序的

1. order by

Hive中的order by跟傳統(tǒng)的sql語(yǔ)言中的order by作用是一樣的,會(huì)對(duì)查詢的結(jié)果做一次全局排序,所以說(shuō),只有hive的sql中制定了order by所有的數(shù)據(jù)都會(huì)到同一個(gè)reducer進(jìn)行處理(不管有多少map,也不管文件有多少的block只會(huì)啟動(dòng)一個(gè)reducer)。但是對(duì)于大量數(shù)據(jù)這將會(huì)消耗很長(zhǎng)的時(shí)間去執(zhí)行。
這里跟傳統(tǒng)的sql還有一點(diǎn)區(qū)別:如果指定了hive.mapred.mode=strict(默認(rèn)值是nonstrict),這時(shí)就必須指定limit來(lái)限制輸出條數(shù),原因是:所有的數(shù)據(jù)都會(huì)在同一個(gè)reducer端進(jìn)行,數(shù)據(jù)量大的情況下可能不能出結(jié)果,那么在這樣的嚴(yán)格模式下,必須指定輸出的條數(shù)。

2. sort by

Hive中指定了sort by,那么在每個(gè)reducer端都會(huì)做排序,也就是說(shuō)保證了局部有序(每個(gè)reducer出來(lái)的數(shù)據(jù)是有序的,但是不能保證所有的數(shù)據(jù)是有序的,除非只有一個(gè)reducer),好處是:執(zhí)行了局部排序之后可以為接下去的全局排序提高不少的效率(其實(shí)就是做一次歸并排序就可以做到全局排序了)。

3. distribute by和sort by一起使用

ditribute by是控制map的輸出在reducer是如何劃分的,舉個(gè)例子,我們有一張表,mid是指這個(gè)store所屬的商戶,money是這個(gè)商戶的盈利,name是這個(gè)store的名字


image.png

執(zhí)行hive語(yǔ)句:
select mid, money, name from store distribute by mid sort by mid asc, money asc
我們所有的mid相同的數(shù)據(jù)會(huì)被送到同一個(gè)reducer去處理,這就是因?yàn)橹付薲istribute by mid,這樣的話就可以統(tǒng)計(jì)出每個(gè)商戶中各個(gè)商店盈利的排序了(這個(gè)肯定是全局有序的,因?yàn)橄嗤纳虘魰?huì)放到同一個(gè)reducer去處理)。這里需要注意的是distribute by必須要寫在sort by之前。

4. cluster by

cluster by的功能就是distribute by和sort by相結(jié)合,如下2個(gè)語(yǔ)句是等價(jià)的:
select mid, money, name from store cluster by mid
select mid, money, name from store distribute by mid sort by mid
如果需要獲得與3中語(yǔ)句一樣的效果:
select mid, money, name from store cluster by mid sort by money
注意被cluster by指定的列只能是降序,不能指定asc和desc。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容