hive分區(qū)表

hive分區(qū)表

1 為什么出現(xiàn)分區(qū)表?

假設(shè)有海量的數(shù)據(jù)保存在hdfs的某一個(gè)hive表明對(duì)應(yīng)的目錄下,使用hive進(jìn)行操作的時(shí)候,往往會(huì)搜索這個(gè)目錄下的所有文件,這有時(shí)會(huì)非常的耗時(shí),如果我們知道 這些數(shù)據(jù)的某些特征,可以事先對(duì)他們進(jìn)行分裂,再把數(shù)據(jù)load到hdfs上的時(shí)候,他們就會(huì)被放到不同的目錄下,然后使用hive進(jìn)行操作的時(shí)候,就可以在where子句中對(duì)這些特征進(jìn)行過濾,那么對(duì)數(shù)據(jù)的操作就只會(huì)在符合條件的子目錄下進(jìn)行,其他不符合條件的目錄下的內(nèi)容就不會(huì)被讀取,在 數(shù)據(jù)量非常大的時(shí)候,這樣節(jié)省大量的時(shí)間,這種把表中的數(shù)據(jù)分散到子目錄下的方式就是分區(qū)表。

2 實(shí)際例子:

某個(gè)電商網(wǎng)站的訂單信息,全部的信息量是非常多的,其中有月份的字段,如果想對(duì)月份進(jìn)行匯總分析,找到哪個(gè)月的訂單最多,hive語(yǔ)句中使用where條件進(jìn)行過濾即可,但是這樣就會(huì)掃描這個(gè)表中所有的文件,不是這個(gè)月的記錄也會(huì)被掃描,極大的浪費(fèi)了時(shí)間,如果能把數(shù)據(jù)按照月份分別存放,那么在查詢的時(shí)候,就只查詢這個(gè)月的數(shù)據(jù)了。

分區(qū)表是hive中一種常見的優(yōu)化手段。

3 創(chuàng)建分區(qū)表語(yǔ)法


hive>create table emp(name string, age int) partitioned by (provice string,city string);

用partitioned by指定創(chuàng)建的分區(qū),多個(gè)分區(qū)意味著多級(jí)目錄。

創(chuàng)建之后hdfs上的目錄結(jié)構(gòu)并不會(huì)立即發(fā)生變化,因?yàn)榇藭r(shí)表中還沒有數(shù)據(jù),往表中插入數(shù)據(jù)之后,會(huì)發(fā)現(xiàn)在表名對(duì)應(yīng)的目錄下,會(huì)多出兩級(jí)目錄。


hive>insert into emp partition(provice = "hebei", city = "baoding") values("tom",22);

hive>dfs -ls -R /user/warehouse/;

輸入命令之后會(huì)大致顯示如下信息:


/user/hive/warehouse/base1.db/emp/provice=hebei

/user/hive/warehouse/base1.db/emp/provice=hebei/city=baoding

/user/hive/warehouse/base1.db/emp/provice=hebei/city=baoding/000000_0

插入的數(shù)據(jù)指定了不同的分區(qū)之后,會(huì)生成不同的文件夾。

3.1 批量load數(shù)據(jù)到不同的分區(qū)上


hive>load data local inpath '/home/user1/emp.txt' overwrite into table t1 partition(provice = "hebei",city = "baoding");

hive>load data local inpath '/home/user1/emp.txt' overwrite into table t1 partition(provice = "hebei",city = "handan");

由于指定了不同的分區(qū),數(shù)據(jù)在上傳時(shí)就會(huì)進(jìn)入不同的目錄下。

4 查看表的分區(qū)信息

在插入兩個(gè)分區(qū)的數(shù)據(jù)之后,查看表的分區(qū)信息,就會(huì)將這個(gè)表的所有分區(qū)都顯示出來。


hive>show partitions database1.table;

OK

provice=hebei/city=baoding

provice=hebei/city=handan

5 使用分區(qū)對(duì)數(shù)據(jù)進(jìn)行過濾

分區(qū)表使用的分區(qū)字段不是在數(shù)據(jù)中存在的(比如創(chuàng)建了一個(gè)國(guó)家分區(qū),但是數(shù)據(jù)中并沒有這個(gè)字段),分區(qū)字段只是為了在HDFS上產(chǎn)生了對(duì)應(yīng)的子目錄。在使用hive查詢的時(shí)候,完全可以使用where對(duì)分區(qū)進(jìn)行過濾。


hive> select * from t3 where city='changchun';

OK

xiaobai 2      jilin  changchun

toms    34      jilin  changchun

haoling 27      jilin  changchun

Time taken: 0.786 seconds, Fetched: 3 row(s)

---------------------------------------------------

hive> select * from t3 where provice = 'jilin';

OK

xiaobai 2      jilin  changchun

toms    34      jilin  changchun

haoling 27      jilin  changchun

Time taken: 0.22 seconds, Fetched: 3 row(s)

6 修改分區(qū)(重構(gòu)分區(qū))

修改分區(qū)意味著對(duì)原有的分區(qū)進(jìn)行增減,即重構(gòu)分區(qū)。

6.1 添加分區(qū)

不改變分區(qū)的級(jí)數(shù),而是改變分區(qū)字段的值。

兩種方式:一種是先插入分區(qū)值,再往上放數(shù)據(jù);二是插入分區(qū)和值同時(shí)進(jìn)行。

方式一

先添加一個(gè)分區(qū)值city = 'shijiazhuang',再往這個(gè)分區(qū)下插入數(shù)據(jù)


hive>alter table emp add partition(provice = "hebei", city = "shijiazhuang");

hive>show partitions emp;

OK

provice=hebei/city=baoding

provice=hebei/city=handan

provice=hebei/city=shijiazhuang

hive>insert into partition(provice = 'hebei', city = 'shijiazhuang') values('tomslee',26);

hive>select * from emp where city = 'shijiazhuang';

tomslee 26  hebei   shijiazhuang

方式二

在插入數(shù)據(jù)的時(shí)候直接指定新的分區(qū),即把創(chuàng)建分區(qū)和插入數(shù)據(jù)兩個(gè)步驟在一次完成


hive>insert into emp partition(provice = 'hebei',city = 'aa') values ('hello',40);

hive> show partitions emp;

OK

provice=hebei/city=aa

provice=hebei/city=baoding

provice=hebei/city=handan

provice=hebei/city=shijiazhuang

Time taken: 0.162 seconds, Fetched: 4 row(s)

7 刪除分區(qū)

分區(qū)對(duì)應(yīng)的是hdfs上的目錄,分區(qū)的刪除涉及到對(duì)應(yīng)的數(shù)據(jù)是否會(huì)被刪除的問題,如果此表是內(nèi)部表的話,那么分區(qū)的刪除意味著對(duì)應(yīng)目錄下的數(shù)據(jù)會(huì)被刪除,如果是外部表的話,分區(qū)的刪除就不會(huì)刪除對(duì)應(yīng)的數(shù)據(jù)文件。

分別創(chuàng)建兩個(gè)分區(qū)表,一個(gè)是管理表,一個(gè)是外部表,并在其中放入一些數(shù)據(jù),然后嘗試刪除分區(qū),查看HDFS上的數(shù)據(jù)是否會(huì)被刪除。


#創(chuàng)建兩個(gè)表,一個(gè)管理表,一個(gè)外部表,都包含一個(gè)分區(qū)

hive> create table managed_t(name string) partitioned by (add string);

hive> create external table ex_table(name string) partitioned by (add string);

#往兩個(gè)表中上傳數(shù)據(jù)

hive> load data local inpath '/home/user1/name.dat' into table managed_table partition(add = 'beijing');

hive> load data local inpath '/home/user1/name.dat' into table ex_table partition(add = 'beijing');

#兩個(gè)表的目錄結(jié)構(gòu)如下:

/user/hive/warehouse/base1.db/ex_table

/user/hive/warehouse/base1.db/ex_table/add=beijing

/user/hive/warehouse/base1.db/ex_table/add=beijing/name.dat

/user/hive/warehouse/base1.db/managed_t

/user/hive/warehouse/base1.db/managed_t/add=beijing

/user/hive/warehouse/base1.db/managed_t/add=beijing/name.dat

#分別刪除兩個(gè)表的分區(qū),再次查看HDFS上的數(shù)據(jù)是否還在

hive>alter table managed_t drop partition (add = 'beijing');

hive>alter table ex_table drop partition (add = 'beijing');

/user/hive/warehouse/base1.db/ex_table

/user/hive/warehouse/base1.db/ex_table/add=beijing

/user/hive/warehouse/base1.db/ex_table/add=beijing/name.dat

/user/hive/warehouse/base1.db/managed_t

從結(jié)果看出,管理表的數(shù)據(jù)已經(jīng)被刪除,只剩下表名(因?yàn)閯h除的是分區(qū),并不是表),但是外部表的數(shù)據(jù)依然存在。

8 動(dòng)態(tài)分區(qū)表

當(dāng)一個(gè)分區(qū)表創(chuàng)建之后,其分區(qū)的值是可以動(dòng)態(tài)修改的(先創(chuàng)建分區(qū)值,再插入數(shù)據(jù);或者是在插入數(shù)據(jù)的時(shí)候指定一個(gè)新的分區(qū)值),這兩種方式都是需要手動(dòng)的去指定分區(qū)值。

當(dāng)分區(qū)變的非常多的時(shí)候(比如氣象站的氣溫記錄數(shù)據(jù),根據(jù)年份分區(qū)之后,還有根據(jù)月份分區(qū),下面可能還有根據(jù)日期分區(qū)),當(dāng)要上傳數(shù)據(jù)到這樣的表中的時(shí)候,手動(dòng)去指定分區(qū)顯然是不現(xiàn)實(shí)的。

這個(gè)時(shí)候,就需要使用到動(dòng)態(tài)分區(qū),動(dòng)態(tài)分區(qū)可以在往表中插入數(shù)據(jù)的時(shí)候,動(dòng)態(tài)的根據(jù)值來選擇數(shù)據(jù)進(jìn)入的分區(qū)。

8.1 動(dòng)態(tài)分區(qū)使用場(chǎng)景

假設(shè)在HDFS上已經(jīng)存在一個(gè)寬表(例如,職員表,這個(gè)表的字段非常多,并且數(shù)據(jù)量也很大),我們想要根據(jù)國(guó)家和省份把這些數(shù)據(jù)放到不同的分區(qū)中,使用動(dòng)態(tài)分區(qū)是十分合適的。

8.2 創(chuàng)建動(dòng)態(tài)分區(qū)表

1.首先創(chuàng)建一個(gè)分區(qū)表,指定兩級(jí)分區(qū),國(guó)家和省份


hive>create table emp(name string,age int)

hive>partitioned by (country string,state string)

hive>row format delimited

hive>fields terminated by '\t'

hive>lines terminated by '\n'

hive>stored as textfile;

2.從寬表中查詢出所需要的字段加載到分區(qū)表中


hive>insert into table emp partition(country,state) select name,age,country,state from t1;

注意:如果出現(xiàn)如下錯(cuò)誤


FAILED: SemanticException [Error 10096]:

Dynamic partition strict mode requires at least one static partition column.

To turn this off set hive.exec.dynamic.partition.mode=nonstrict

嚴(yán)格模式下,不允許所有的分區(qū)都被動(dòng)態(tài)指定,目的是為了防止生成太多的目錄.通過下面語(yǔ)句可以解決問題:


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

這里就是動(dòng)態(tài)分區(qū)的關(guān)鍵:

在指定分區(qū)的時(shí)候,不指定其值,而只是指定分區(qū)的名稱,在后面的查詢語(yǔ)句中,所查詢的最后兩個(gè)字段就會(huì)被對(duì)應(yīng)到這兩個(gè)分區(qū)上,也就是說,前面分區(qū)不指定值的話,就會(huì)到后面的查詢語(yǔ)句中去動(dòng)態(tài)的尋找值,這時(shí)可以想象,后面的查詢語(yǔ)句的字段必須是大于等于前面的分區(qū)數(shù);

8.3 半動(dòng)態(tài)分區(qū)表

所謂半動(dòng)態(tài)分區(qū)就是并不是所有的分區(qū)值都是動(dòng)態(tài)指定的,其中有一部分是固定值,另一部分需要在查詢列中動(dòng)態(tài)賦值,例如:


hive>insert into table emp partition(country = 'US',state)

hive>select name,age,country,state from t1;

上述語(yǔ)句中,分區(qū)country就是一個(gè)固定的值US,state的值沒有指定,而是動(dòng)態(tài)賦值,半分區(qū)模式需要注意的是,動(dòng)態(tài)分區(qū)必須放在最后。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容