兩種Hive表
hive存儲(chǔ):數(shù)據(jù)+元數(shù)據(jù)
托管表(內(nèi)部表)
創(chuàng)建表:
hive> create table test2(id int,name String,tel String)
> ROW FORMAT DELIMITED
> FIELDS TERMINATED BY ',';
準(zhǔn)備數(shù)據(jù)文件my.txt
1,scc0,20,131888888888
2,scc1,22,13222222222
3,scc2,21,183938384983
灌數(shù)據(jù):
load data local inpath '/usr/local/src/my.txt' into table test2;
查看數(shù)據(jù):
hive> select * from test2;
OK
1 scc0 20
2 scc1 22
3 scc2 21
Time taken: 0.132 seconds, Fetched: 3 row(s)
hdfs中的warehouse文件夾下面會(huì)多一個(gè)文件夾叫做test2。里面的文件名叫做my.txt
刪除表:
hive> drop table test2;
OK
Time taken: 0.43 seconds
warehouse文件夾下的test2以及里面的所有文件被刪除。內(nèi)部表刪除會(huì)同時(shí)刪除元數(shù)據(jù)和數(shù)據(jù)文件。在建表的時(shí)候可以指定location,創(chuàng)建的內(nèi)部表默認(rèn)是存在warehouse/[tablename],也可以指定目錄存放。
create table test2(id int,name String,tel String) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' location '/scc/tmpdir';
外部表
創(chuàng)建表:
多加一個(gè)關(guān)鍵詞external
create table test3(id int,name String,tel String) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
也可以指定location。默認(rèn)還是放在warehouse/[tablename]
灌數(shù)據(jù)方式同上。
查看方式同上。
刪除命令同上:
刪除后查詢:
hive> show tables;
OK
haha
Time taken: 0.034 seconds, Fetched: 1 row(s)
表中已經(jīng)不再存在test3, 但是HDFS中的目錄以及文件均存在。說明外部表在刪除的時(shí)候僅僅刪除了元數(shù)據(jù),并未刪除存儲(chǔ)文件。
分區(qū)和桶
表大于分區(qū)大于桶
參考此鏈接
1. 先說分區(qū)
在HDFS中,分區(qū)的表現(xiàn)為表的子目錄。
在創(chuàng)建分區(qū)的命令上,分區(qū)表現(xiàn)為指定分區(qū)partitioned by (partitio-name string)
在查詢方式上,分區(qū)就相當(dāng)于表的字段。
創(chuàng)建帶分區(qū)(以時(shí)間time為分區(qū))的表:
create table tbhaspar(id int,name string,tel string) partitioned by(time string) row format delimited fields terminated by ',';
準(zhǔn)備數(shù)據(jù):
(下面數(shù)據(jù)中不含time字段,也可以帶有time字段,如果按照下面灌數(shù)據(jù)的方式,帶有的time字段的數(shù)據(jù)會(huì)被分區(qū)名覆蓋掉)
1,scc0,131888888888
2,scc1,13222222222
3,scc2,183938384983
4,scc3,16222232222
5,scc4,17222222222
灌數(shù)據(jù):
load data local inpath '/usr/local/src/my.txt' into table tbhaspar partition (time='03-01');
load data local inpath '/usr/local/src/my.txt' into table tbhaspar partition (time='03-02');
load data local inpath '/usr/local/src/my.txt' into table tbhaspar partition (time='03-03');
查詢
(創(chuàng)建表的時(shí)候指定了3個(gè)字段1個(gè)分區(qū),接下來的查詢結(jié)果就好像是看到了4個(gè)字段):
hive> select * from tbhaspar;
OK
1 scc0 131888888888 03-01
2 scc1 13222222222 03-01
3 scc2 183938384983 03-01
4 scc3 16222232222 03-01
5 scc4 17222222222 03-01
1 scc0 131888888888 03-02
2 scc1 13222222222 03-02
3 scc2 183938384983 03-02
4 scc3 16222232222 03-02
5 scc4 17222222222 03-02
1 scc0 131888888888 03-03
2 scc1 13222222222 03-03
3 scc2 183938384983 03-03
4 scc3 16222232222 03-03
5 scc4 17222222222 03-03
Time taken: 0.081 seconds, Fetched: 15 row(s)
查看表信息:
hive> describe tbhaspar;
OK
id int
name string
tel string
time string
# Partition Information
# col_name data_type comment
time string
Time taken: 0.09 seconds, Fetched: 9 row(s)
指定分區(qū)查詢
(下面的查詢方式,好像分區(qū)真的是一個(gè)字段):
select * from tbhaspar where time = '03-01';
對(duì),上面說的都是
靜態(tài)分區(qū),下面看看動(dòng)態(tài)分區(qū)。
動(dòng)態(tài)分區(qū)
可以根據(jù)查詢得到的數(shù)據(jù)動(dòng)態(tài)分配到分區(qū)里。其實(shí)動(dòng)態(tài)分區(qū)與靜態(tài)分區(qū)區(qū)別就是不指定分區(qū)目錄,由系統(tǒng)自己選擇。
該功能需要手動(dòng)開啟:
hive> set hive.exec.dynamic.partition=true;
- 創(chuàng)建一個(gè)跟剛才一樣的分區(qū)表id,name,tel partition=time
- 灌數(shù)據(jù)。灌數(shù)據(jù)的方式只能通過從別的表查詢得到,不能直接從local文件加載。我們下面從剛才的靜態(tài)分區(qū)表進(jìn)行加載(當(dāng)然我們此時(shí)把分區(qū)表當(dāng)成未分區(qū)表來用,現(xiàn)實(shí)中都是先把數(shù)據(jù)加載到普通表,然后再讀取并加載到動(dòng)態(tài)分區(qū)中)。
hive> insert overwrite table tbhasdypar partition(time) select * from tbhaspar;
執(zhí)行完就開始調(diào)MR了。。等一會(huì)兒看結(jié)果!直接就分區(qū)了!很帥!

2. 再說桶
桶是更細(xì)粒度的數(shù)據(jù)范圍劃分。桶的作用體現(xiàn)之一:MR階段可以大大減少Join操作(別人這么說的,我不知道)。
Hive采用對(duì)列值哈希,然后除以桶的個(gè)數(shù)求余的方式?jīng)Q定該條記錄存放在哪個(gè)桶當(dāng)中。
建一個(gè)帶桶的表
按照id分成3個(gè)桶。
hive> create table buck2 (id int,name string) clustered by (id) sorted by(id) into 3 buckets row format delimited fields terminated by ',' stored as textfile;
灌數(shù)據(jù)
先看一眼我們要灌的數(shù)據(jù)

hive> insert overwrite table buck2 select id,name from tbhaspar;
看結(jié)果
看結(jié)果之前,先設(shè)置一下這個(gè):
set mapreduce.job.reduces=4;
為什么?因?yàn)榉謪^(qū)的效果就是在MapReduce中體現(xiàn)出來的。我們?cè)O(shè)置多個(gè)Reduce觀察一下排序結(jié)果。

HDFS的buck2下面多了三個(gè)文件夾,對(duì)應(yīng)值hash得到的三種余數(shù)。
執(zhí)行:
hive> select * from buck2 ;
下圖結(jié)果中,正好是三個(gè)桶,而且是hash分桶,很明顯。

上面是一個(gè)無序結(jié)果。下面的命令可以查看有序的結(jié)果。會(huì)在每個(gè)reduce里面排序。
hive> select * from buck2 sort by id ;
Hive避免MapReduce
把這個(gè)屬性設(shè)置為true
hive.exec.mode.local.auto=true
hive在運(yùn)行的時(shí)候嘗試先使用本地模式運(yùn)行 否則幾乎所有的操作都會(huì)觸發(fā)MR
分區(qū)查詢-strict嚴(yán)格模式
hive.mapred.mode=strict
上述參數(shù) 嚴(yán)格模式下 如果針對(duì)分區(qū)表的查詢,where子句沒有添加分區(qū)過濾的話,任務(wù)禁止提交。
hive.mapred.mode=nonstrict
上述參數(shù) 取消嚴(yán)格模式
Hive數(shù)據(jù)傾斜問題 以及解決思路
MR階段,Map產(chǎn)生的數(shù)據(jù)是根據(jù)Hash算法生成的key,按key選擇合適的reduce,會(huì)因?yàn)閿?shù)據(jù)特殊性引起的key聚集,造成某些Reduce任務(wù)繁重,某些reduce幾乎沒有任務(wù)。
配置參數(shù):
hive.map.aggr=true//Map 端部分聚合,相當(dāng)于Combiner
hive.groupby.skewindata=true
原理就是:將數(shù)據(jù)隨機(jī)分成兩個(gè)Job,第一個(gè)job隨機(jī)分到不同的reduce,很有可能出現(xiàn)相同的key在不同的reduce里面。第二個(gè)Job可以根據(jù)預(yù)處理的反饋,將key分配到對(duì)應(yīng)的reduce中,基本上同一個(gè)key都在一個(gè)reduce里面。整體上可以減少數(shù)據(jù)處理時(shí)間,做到負(fù)載均衡。
SQL調(diào)節(jié):
- 如果兩個(gè)表都是大表,那么可以對(duì)key較少的那部分,可以賦一個(gè)隨機(jī)的key,值為null。傾斜的數(shù)據(jù)可以分配到不同的reduce上,null值也不會(huì)影響最后的結(jié)果計(jì)算。
- 如果表一大一小(約定1000條記錄一下),內(nèi)存加載較小的表在map端完成redcue操作。
還有其他方法,沒使用過,略去不表。
Hive中的order by,sort by,distribute by, cluster by作用以及用法
- order by:在查詢的時(shí)候sql指定,進(jìn)行全局排序。不管會(huì)有多少個(gè)map節(jié)點(diǎn),只會(huì)在一個(gè)reduce節(jié)點(diǎn)內(nèi)進(jìn)行處理,所以會(huì)很慢。并且,如果手動(dòng)設(shè)置了嚴(yán)格模式,還是必須要指定limit條數(shù)的,因?yàn)閿?shù)據(jù)量非常大,可能不會(huì)出結(jié)果。
- sort by:原理類似于歸并排序。在每個(gè)reduce節(jié)點(diǎn)進(jìn)行排序,做到局部有序,最后進(jìn)行全局排序的時(shí)候就可以提升不少的效率。
- distribute by:都是和sort by 一起使用,并且先于它。作用是將指定的字段值相同的,分配到同一個(gè)reduce進(jìn)行處理。參考這個(gè)鏈接- distribute by和sort by一起使用
- cluster by:是2,3的合并
cluster by id等價(jià)于distibute by id sort by id
和3中語句等價(jià)的語句:
select mid, money, name from store cluster by mid sort by money
Hive文件存儲(chǔ)、壓縮格式
- text file
默認(rèn)設(shè)置。建表時(shí)會(huì)把數(shù)據(jù)文件拷貝到hdfs上不進(jìn)行處理。 - sequence file
二進(jìn)制存儲(chǔ)。分割,壓縮比較方便。使用<key,value>存儲(chǔ),key是空的。
三種壓縮可選,None,Record,Block。Record效率低一些,一般用Block - rc file行列存儲(chǔ) 不好用
- orc file 3的升級(jí)版。性能很好,存儲(chǔ)效率比text file節(jié)省很多。
從本地加載數(shù)據(jù)只用用text file格式。然后才可以通過text file轉(zhuǎn)換成2,3,4的格式。
text file文件可以直接通過cat 查看。而2,3,4的源文件無法直接查看,只能借助表查詢才能查看其中的內(nèi)容。
=====================
我的其他相關(guān)文章: