HIVE 動態分割槽的乙個坑

2021-08-18 14:06:08 字數 1355 閱讀 1732

在hive sql中使用動態分割槽非常方便,也比較常用,但是在使用的過程中會帶來一些問題,比如:在一段sql語句中我需要指定兩個字段當做動態分割槽,乙個欄位的基數為7,另乙個為4,這就是28個分割槽,我們的sql語句的最後乙個job是乙個僅有map階段的任務,資料量大有4000個map,這種情況下map任務在往hive分割槽中寫的時候,每個map幾乎都要產生28個檔案,這樣就會產生4000*28個檔案,帶來大量的小檔案。比如如下乙個簡單的sql:

insert overwrite table test1 partition(week,type)

select

*from test_table

這個sql只有map任務,在資料量的情況下可能會產生大量的map,導致產生大量的小檔案,實際上不僅僅是最後乙個job只有map的任務有影響,reduce同樣如此,但是一般情況下reduce的數目不會太大,並且reduce數目比較好控制。

1.最後乙個階段只有map,若是有reduce的話,把相同分割槽的資料傳送到乙個reduce處理,不就解決了麼。因此可以這樣

insert overwrite table test1 partition(week,type)

select

*from test_table

distribute by week,type;

這樣的話產生的檔案數就等於分割槽數目了(在不限制reduce的情況下),檔案數目大大減小,但是檔案數目也太少了吧,並且由於資料分布不均勻,分割槽下的檔案大小差異特別大。並且由於不同reduce處理的資料量差異,造成部分reduce執行速度過慢,影響了整體的速度,

2.若是想把資料均勻的分配的reduce上,distribute by的字段就不能使用分割槽下的字段,可以使用distribute by rand(),這樣rand取雜湊然後對reduce數目取餘,保證了每條資料分配到所有reduce的可能性是相等的,這樣reduce處理的資料量就是均勻的,在資料量比較大的情況下每個reduce產生的檔案數為動態分割槽的個數,產生的檔案總個數m*分割槽個數。

set hive.exec.reducers.max=500;

insert overwrite table test1 partition(week,type)

select

*from test_table

distribute by rand();

比如上邊例子就是 500*28個檔案,大大減小了檔案數。

實際上還有個最笨的方法就是控制map數,但是map數不能夠小於檔案數,除非進行檔案合併(帶來額外消耗),這樣的話通過這種方法依賴於上個階段的檔案數目。並且map數往往難以控制,若是乙個每天執行的任務,資料量每天不一樣帶來了不確定性。

Hive的分割槽(partition) 動態分割槽

分割槽是hive存放資料的一種方式。將列值作為目錄來存放資料,就是乙個分割槽。這樣查詢時使用分割槽列進行過濾,只需根據列值直接掃瞄對應目錄下的資料,不掃瞄其他不關心的分割槽,快速定位,提高查詢效率。hive中支援兩種型別的分割槽 靜態分割槽sp static partition 動態分割槽dp dy...

Hive 動態分割槽的使用

set hive.exec.dynamic.partition true set hive.exec.dynamic.partition.mode nonstrict 預設是strict嚴格模式,至少要有乙個靜態分割槽。將下表按照location進行分割槽 建立分割槽表 create table d...

hive中的動態分割槽和靜態分割槽

對於向一張hive分割槽表寫入資料,一般可以這樣 insert into tb partition par col par value select id,name from tb1 這樣,資料都會被插入到tb表的par value分割槽下。有時候我們會遇到這樣的場景 tb1表下有個字段,比如mon...