為了對表進行合理的管理以及提高查詢效率,Hive可以將表組織成“分區”。一個分區實際上就是表下的一個目錄,一個表可以在多個維度上進行分區,分區之間的關系就是目錄樹的關系。
1、創建分區表
通過PARTITIONED BY子句指定,分區的順序決定了誰是父目錄,誰是子目錄。
創建有一個分區的分區表:
CREATE TABLE IF NOT EXISTS part_test(
c1 string
,c2 string
,c3 string
,c4 string
)PARTITIONED BY (day_id string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'
STORED AS TEXTFILE;
創建有兩個分區的分區表:
CREATE TABLE IF NOT EXISTS part_test_1(
c1 string
,c2 string
,c3 string
,c4 string
) PARTITIONED BY (month_id string,day_id string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'
STORED AS TEXTFILE;
2、 外部分區表
外部表也可以建成分區表,如hdfs目錄/user/tuoming/part下有
201805和201806兩個目錄,201805下有一個20180509子目錄,201806下有20180609和20180610兩個子目錄。
創建一個映射到/user/tuoming/part目錄的外部分區表:
CREATE EXTERNAL TABLE IF NOT EXISTS part_test_2(
c1 string
,c2 string
,c3 string
,c4 string
)PARTITIONED BY (month_id string,day_id string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/user/tuoming/part';
為part_test_2增加分區:
alter table part_test_2 add partition(month_id='201805',day_id='20180509') location '/user/tuoming/part/201805/20180509';
alter table part_test_2 add partition(month_id='201806',day_id='20180609') location '/user/tuoming/part/201806/20180609';
alter table part_test_2 add partition(month_id='201806',day_id='20180610') location '/user/tuoming/part/201806/20180610';
使用show partitions語句查看part_test_2有哪些分區:
show partitions part_test_2;
3、 內部分區表
創建一個主分區為month_id,子分區為day_id的內部分區表:
CREATE TABLE IF NOT EXISTS part_test_3(
c1 string
,c2 string
,c3 string
,c4 string
)PARTITIONED BY (month_id string,day_id string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'
STORED AS TEXTFILE;
為內部分區表加載數據
(1)使用load data inpath…overwrite into table partition語句從hdfs目錄加載:
load data inpath '/user/tuoming/test/test' overwrite into table part_test_3 partition(month_id='201805',day_id='20180509');
數據內容如下:
(2)使用insert overwrite table/ insert into…partition語句從查詢結果中加載:
覆蓋插入:
insert overwrite table part_test_3 partition(month_id='201805',day_id='20180509') select * from part_test_temp;
追加插入:
insert into part_test_3 partition(month_id='201805',day_id='20180509') select * from part_test_temp;
注意:使用以上兩種方法為內部分區表加載數據不需要預創建分區,加載數據時會自動創建相應的分區。如果想要為內部表預先創建分區,需要使用hadoop fs –mkdir命令在表目錄下先創建相應的分區目錄,然后再使用alter table add partition語句增加分區:
4、 刪除分區
使用alter table…drop partition語句刪除對應分區:
alter table part_test_3 drop partition(day_id='20180509');
注意:外部分區表使用alter table…drop partition語句刪除分區,只會刪除元數據,相應的目錄和文件並不會刪除。內部表使用該語句刪除分區,既會刪除元數據,也會刪除相應的目錄和數據文件。
5、 動態分區
上述使用insert overwrite table…partition…從查詢結果加載數據到分區,必須指定特定的分區,而且每個分區都需要使用一條插入語句。當需要一次插入多個分區的數據時,可以使用動態分區,根據查詢得到的數據動態分配到分區里。動態分區與靜態分區的區別就是不指定分區目錄,由hive根據實際的數據選擇插入到哪一個分區。
#啟動動態分區功能
set hive.exec.dynamic.partition=true;
#允許全部分區都是動態分區
set hive.exec.dynamic.partition.mode=nostrick;
#month_id為靜態分區,day_id為動態分區:
insert overwrite table dynamic_test partition(month_id='201710',day_id)
select c1,c2,c3,c4,c5,c6,c7,day_id from kafka_offset
where substr(day_id,1,6)='201710';
# month_id和 day_id均為動態分區:
insert overwrite table dynamic_test partition(month_id,day_id)
select c1,c2,c3,c4,c5,c6,c7,substr(day_id,1,6) as month_id,day_id from kafka_offset;
為了讓分區列的值相同的數據盡量在同一個mapreduce中,這樣每一個mapreduce可以盡量少的產生新的文件夾,可以借助distribute by的功能,將分區列值相同的數據放到一起。
insert overwrite table dynamic_test partition(month_id,day_id)
select c1,c2,c3,c4,c5,c6,c7,substr(day_id,1,6) as month_id,day_id from kafka_offset
distribute by month_id,day_id;