1. 程式人生 > 其它 >Hive分割槽(靜態分割槽+動態分割槽)

Hive分割槽(靜態分割槽+動態分割槽)

Hive分割槽的概念與傳統關係型資料庫分割槽不同。

傳統資料庫的分割槽方式:就oracle而言,分割槽獨立存在於段裡,裡面儲存真實的資料,在資料進行插入的時候自動分配分割槽。

Hive的分割槽方式:由於Hive實際是儲存在HDFS上的抽象,Hive的一個分割槽名對應一個目錄名,子分割槽名就是子目錄名,並不是一個實際欄位。

所以可以這樣理解,當我們在插入資料的時候指定分割槽,其實就是新建一個目錄或者子目錄,或者在原有的目錄上新增資料檔案。

Hive分割槽的建立

Hive分割槽是在建立表的時候用Partitioned by 關鍵字定義的,但要注意,Partitioned by子句中定義的列是表中正式的列,但是Hive下的資料檔案中並不包含這些列,因為它們是目錄名。

靜態分割槽

建立一張靜態分割槽表par_tab,單個分割槽

create table par_tab (name string,nation string) partitioned by (sex string) row format delimited fields terminated by ',';

這時候通過desc檢視的表結構如下

hive> desc par_tab;
OK
name                    string                                      
nation                  string                                      
sex                     string                                      
          
# Partition Information          
# col_name                data_type               comment             
          
sex                     string                                      
Time taken: 0.038 seconds, Fetched: 8 row(s)

準備本地資料檔案par_tab.txt,內容 “名字/國籍”,將以性別(sex)作為分割槽

jan,china
mary,america
lilei,china
heyong,china
yiku,japan
emoji,japan

把資料插入到表(其實load操作相當於把檔案移動到HDFS的Hive目錄下)

load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab partition (sex='man');

這時候在hive下查詢par_tab表,變成了3列,注意。

hive> select * from par_tab;
OK
jan    china    man
mary    america    man
lilei    china    man
heyong    china    man
yiku    japan    man
emoji    japan    man
Time taken: 0.076 seconds, Fetched: 6 row(s)

檢視par_tab目錄結構

[hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab

drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man
-rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man/par_tab.txt

可以看到,在新建分割槽表的時候,系統會在hive資料倉庫預設路徑/user/hive/warehouse/下建立一個目錄(表名),再建立目錄的子目錄sex=man(分割槽名),最後在分割槽名下存放實際的資料檔案。

如果再插入另一個數據檔案資料,如檔案

lily,china
nancy,china
hanmeimei,america

插入資料

load data local inpath '/home/hadoop/files/par_tab_wm.txt' into table par_tab partition (sex='woman');

檢視par_tab表目錄結構

[hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man
-rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man/par_tab.txt
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:35 /user/hive/warehouse/par_tab/sex=woman
-rwxr-xr-x   1 hadoop supergroup         41 2017-03-29 08:35 /user/hive/warehouse/par_tab/sex=woman/par_tab_wm.txt

最後檢視兩次插入的結果,包含了man和woman

hive> select * from par_tab;
OK
jan    china    man
mary    america    man
lilei    china    man
heyong    china    man
yiku    japan    man
emoji    japan    man
lily    china    woman
nancy    china    woman
hanmeimei    america    woman
Time taken: 0.136 seconds, Fetched: 9 row(s)

因為分割槽列是表實際定義的列,所以查詢分割槽資料時

hive> select * from par_tab where sex='woman';
OK
lily    china    woman
nancy    china    woman
hanmeimei    america    woman
Time taken: 0.515 seconds, Fetched: 3 row(s)

下面建立一張靜態分割槽表par_tab_muilt,多個分割槽(性別+日期)

hive> create table par_tab_muilt (name string, nation string) partitioned by (sex string,dt string) row format delimited fields terminated by ',' ;
hive> load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab_muilt partition (sex='man',dt='2017-03-29');


[hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab_muilt
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2017-03-29
-rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2017-03-29/par_tab.txt

可見,新建表的時候定義的分割槽順序,決定了檔案目錄順序(誰是父目錄誰是子目錄),正因為有了這個層級關係,當我們查詢所有man的時候,man以下的所有日期下的資料都會被查出來。如果只查詢日期分割槽,但父目錄sex=man和sex=woman都有該日期的資料,那麼Hive會對輸入路徑進行修剪,從而只掃描日期分割槽,性別分割槽不作過濾(即查詢結果包含了所有性別)。

動態分割槽

如果用上述的靜態分割槽,插入的時候必須首先要知道有什麼分割槽型別,而且每個分割槽寫一個load data,太煩人。使用動態分割槽可解決以上問題,其可以根據查詢得到的資料動態分配到分割槽裡。其實動態分割槽與靜態分割槽區別就是不指定分割槽目錄,由系統自己選擇。

首先,啟動動態分割槽功能

hive> set hive.exec.dynamic.partition=true;

假設已有一張表par_tab,前兩列是名稱name和國籍nation,後兩列是分割槽列,性別sex和日期dt,資料如下

hive> select * from par_tab;
OK
lily    china    man    2013-03-28
nancy    china    man    2013-03-28
hanmeimei    america    man    2013-03-28
jan    china    man    2013-03-29
mary    america    man    2013-03-29
lilei    china    man    2013-03-29
heyong    china    man    2013-03-29
yiku    japan    man    2013-03-29
emoji    japan    man    2013-03-29
Time taken: 1.141 seconds, Fetched: 9 row(s)

現在我把這張表的內容直接插入到另一張表par_dnm中,並實現sex為靜態分割槽,dt動態分割槽(不指定到底是哪日,讓系統自己分配決定)

hive> insert overwrite table par_dnm partition(sex='man',dt)
    > select name, nation, dt from par_tab;

插入後看下目錄結構

drwxr-xr-x   - hadoop supergroup          0 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-28
-rwxr-xr-x   1 hadoop supergroup         41 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-28/000000_0
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-29
-rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-29/000000_0

再檢視分割槽數

hive> show partitions par_dnm;
OK
sex=man/dt=2013-03-28
sex=man/dt=2013-03-29
Time taken: 0.065 seconds, Fetched: 2 row(s)

證明動態分割槽成功。

注意,動態分割槽不允許主分割槽採用動態列而副分割槽採用靜態列,這樣將導致所有的主分割槽都要建立副分割槽靜態列所定義的分割槽。

動態分割槽可以允許所有的分割槽列都是動態分割槽列,但是要首先設定一個引數hive.exec.dynamic.partition.mode :

hive> set hive.exec.dynamic.partition.mode;
hive.exec.dynamic.partition.mode=strict

它的預設值是strick,即不允許分割槽列全部是動態的,這是為了防止使用者有可能原意是隻在子分割槽內進行動態建分割槽,但是由於疏忽忘記為主分割槽列指定值了,這將導致一個dml語句在短時間內建立大量的新的分割槽(對應大量新的資料夾),對系統性能帶來影響。
所以我們要設定:

hive> set hive.exec.dynamic.partition.mode=nostrick;

轉自:https://www.cnblogs.com/yongjian/archive/2017/03/29/6640951.html