Hive分區(靜態分區+動態分區)

原文地址: https://www.cnblogs.com/yongjian/archive/2017/03/29/6640951.htmlhtml

  Hive分區的概念與傳統關係型數據庫分區不一樣。   傳統數據庫的分區方式:就oracle而言,分區獨立存在於段裏,裏面存儲真實的數據,在數據進行插入的時候自動分配分區。   Hive的分區方式:因爲Hive實際是存儲在HDFS上的抽象,Hive的一個分區名對應一個目錄名,子分區名就是子目錄名,並非一個實際字段。sql

  因此能夠這樣理解,當咱們在插入數據的時候指定分區,其實就是新建一個目錄或者子目錄,或者在原有的目錄上添加數據文件。數據庫

Hive分區的建立

  Hive分區是在建立表的時候用Partitioned by 關鍵字定義的,但要注意,Partitioned by子句中定義的列是表中正式的列,可是Hive下的數據文件中並不包含這些列,由於它們是目錄名。oracle

靜態分區

  建立一張靜態分區表par_tab,單個分區oop

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)做爲分區ui

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

  把數據插入到表(其實load操做至關於把文件移動到HDFS的Hive目錄下)url

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

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

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目錄結構.net

[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

  它的默認值是strict,即不容許分區列所有是動態的,這是爲了防止用戶有可能原意是隻在子分區內進行動態建分區,可是因爲疏忽忘記爲主分區列指定值了,這將致使一個dml語句在短期內建立大量的新的分區(對應大量新的文件夾),對系統性能帶來影響。 因此咱們要設置:

hive> set hive.exec.dynamic.partition.mode=nostrict;
相關文章
相關標籤/搜索