Hive知識匯總


兩種Hive表

hive存儲:數據+元數據

托管表(內部表)

創建表:

hive> create table test2(id int,name String,tel String)
    > ROW FORMAT DELIMITED
    > FIELDS TERMINATED BY ',';

准備數據文件my.txt

1,scc0,20,131888888888
2,scc1,22,13222222222
3,scc2,21,183938384983

灌數據:

load data local inpath '/usr/local/src/my.txt' into table test2;

查看數據:

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文件夾下面會多一個文件夾叫做test2。里面的文件名叫做my.txt
刪除表:

hive> drop table test2;
OK
Time taken: 0.43 seconds

warehouse文件夾下的test2以及里面的所有文件被刪除。內部表刪除會同時刪除元數據和數據文件。在建表的時候可以指定location,創建的內部表默認是存在warehouse/[tablename],也可以指定目錄存放。

create table test2(id int,name String,tel String) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' location '/scc/tmpdir';

外部表

創建表:
多加一個關鍵詞external

create table test3(id int,name String,tel String) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

也可以指定location。默認還是放在warehouse/[tablename]
灌數據方式同上。
查看方式同上。
刪除命令同上:
刪除后查詢:

hive> show tables;
OK
haha
Time taken: 0.034 seconds, Fetched: 1 row(s)

表中已經不再存在test3, 但是HDFS中的目錄以及文件均存在。說明外部表在刪除的時候僅僅刪除了元數據,並未刪除存儲文件。

分區和桶

表大於分區大於桶
參考此鏈接

1. 先說分區

在HDFS中,分區的表現為表的子目錄。
在創建分區的命令上,分區表現為指定分區partitioned by (partitio-name string)
在查詢方式上,分區就相當於表的字段。

創建帶分區(以時間time為分區)的表:
create table tbhaspar(id int,name string,tel string) partitioned by(time string)  row format delimited fields terminated by ',';
准備數據:

(下面數據中不含time字段,也可以帶有time字段,如果按照下面灌數據的方式,帶有的time字段的數據會被分區名覆蓋掉)

1,scc0,131888888888
2,scc1,13222222222
3,scc2,183938384983
4,scc3,16222232222
5,scc4,17222222222
灌數據:
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'); 
查詢

(創建表的時候指定了3個字段1個分區,接下來的查詢結果就好像是看到了4個字段):

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)

指定分區查詢

(下面的查詢方式,好像分區真的是一個字段):

select * from tbhaspar where time = '03-01';

對,上面說的都是靜態分區,下面看看動態分區。

動態分區

可以根據查詢得到的數據動態分配到分區里。其實動態分區與靜態分區區別就是不指定分區目錄,由系統自己選擇。
該功能需要手動開啟:

hive> set hive.exec.dynamic.partition=true;
  1. 創建一個跟剛才一樣的分區表id,name,tel partition=time
  2. 灌數據。灌數據的方式只能通過從別的表查詢得到,不能直接從local文件加載。我們下面從剛才的靜態分區表進行加載(當然我們此時把分區表當成未分區表來用,現實中都是先把數據加載到普通表,然后再讀取並加載到動態分區中)。
hive> insert  overwrite  table  tbhasdypar partition(time) select * from tbhaspar; 

執行完就開始調MR了。。等一會兒看結果!直接就分區了!很帥!

2. 再說桶

桶是更細粒度的數據范圍划分。桶的作用體現之一:MR階段可以大大減少Join操作(別人這么說的,我不知道)。
Hive采用對列值哈希,然后除以桶的個數求余的方式決定該條記錄存放在哪個桶當中。

建一個帶桶的表

按照id分成3個桶。

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;  
灌數據

先看一眼我們要灌的數據

hive> insert overwrite table buck2 select id,name from tbhaspar;
看結果

看結果之前,先設置一下這個:

set mapreduce.job.reduces=4;

為什么?因為分區的效果就是在MapReduce中體現出來的。我們設置多個Reduce觀察一下排序結果。

HDFS的buck2下面多了三個文件夾,對應值hash得到的三種余數。
執行:

hive> select * from buck2 ;

下圖結果中,正好是三個桶,而且是hash分桶,很明顯。

上面是一個無序結果。下面的命令可以查看有序的結果。會在每個reduce里面排序。

hive> select * from buck2 sort by id ;

Hive避免MapReduce

把這個屬性設置為true

hive.exec.mode.local.auto=true

hive在運行的時候嘗試先使用本地模式運行 否則幾乎所有的操作都會觸發MR

分區查詢-strict嚴格模式

hive.mapred.mode=strict

上述參數 嚴格模式下 如果針對分區表的查詢,where子句沒有添加分區過濾的話,任務禁止提交。

hive.mapred.mode=nonstrict

上述參數 取消嚴格模式

Hive數據傾斜問題 以及解決思路

MR階段,Map產生的數據是根據Hash算法生成的key,按key選擇合適的reduce,會因為數據特殊性引起的key聚集,造成某些Reduce任務繁重,某些reduce幾乎沒有任務。
配置參數
hive.map.aggr=true//Map 端部分聚合,相當於Combiner
hive.groupby.skewindata=true
原理就是:將數據隨機分成兩個Job,第一個job隨機分到不同的reduce,很有可能出現相同的key在不同的reduce里面。第二個Job可以根據預處理的反饋,將key分配到對應的reduce中,基本上同一個key都在一個reduce里面。整體上可以減少數據處理時間,做到負載均衡。
SQL調節

  1. 如果兩個表都是大表,那么可以對key較少的那部分,可以賦一個隨機的key,值為null。傾斜的數據可以分配到不同的reduce上,null值也不會影響最后的結果計算。
  2. 如果表一大一小(約定1000條記錄一下),內存加載較小的表在map端完成redcue操作。
    還有其他方法,沒使用過,略去不表。

Hive中的order by,sort by,distribute by, cluster by作用以及用法

  1. order by:在查詢的時候sql指定,進行全局排序。不管會有多少個map節點,只會在一個reduce節點內進行處理,所以會很慢。並且,如果手動設置了嚴格模式,還是必須要指定limit條數的,因為數據量非常大,可能不會出結果。
  2. sort by:原理類似於歸並排序。在每個reduce節點進行排序,做到局部有序,最后進行全局排序的時候就可以提升不少的效率。
  3. distribute by:都是和sort by 一起使用,並且先於它。作用是將指定的字段值相同的,分配到同一個reduce進行處理。參考這個鏈接- distribute by和sort by一起使用
  1. cluster by:是2,3的合並
    cluster by id等價於distibute by id sort by id
    和3中語句等價的語句:
select mid, money, name from store cluster by mid sort by money  

Hive文件存儲、壓縮格式

  1. text file
    默認設置。建表時會把數據文件拷貝到hdfs上不進行處理。
  2. sequence file
    二進制存儲。分割,壓縮比較方便。使用<key,value>存儲,key是空的。
    三種壓縮可選,None,Record,Block。Record效率低一些,一般用Block
  3. rc file行列存儲 不好用
  4. orc file 3的升級版。性能很好,存儲效率比text file節省很多。
    從本地加載數據只用用text file格式。然后才可以通過text file轉換成2,3,4的格式。
    text file文件可以直接通過cat 查看。而2,3,4的源文件無法直接查看,只能借助表查詢才能查看其中的內容。

=====================
我的其他相關文章:

  1. Hive知識匯總
  2. 大數據研發相關-面試拾遺(備戰積累的知識點)
  3. 2018年春招面試實戰記錄-大數據開發相關崗位
  4. HadoopMR-Spark-HBase-Hive


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM