Hive筆記2:Hive分區、Hive動態分區
目錄
一、Hive 分區
分區表實際上是在表的目錄下再建一個子目錄
作用:進行分區裁剪,避免全表掃描,減少MapReduce處理的數據量,提高效率
一般在公司的hive中,所有的表基本上都是分區表,通常按日期分區、地域分區
分區表在使用的時候記得加上分區字段
分區也不是越多越好,一般不超過3級,根據實際業務衡量
建立分區表:
create external table students_pt1
(
id bigint,
name string,
age int,
gender string,
clazz string
)
PARTITIONED BY(pt string) #建立分區表必須加的語句,括號內指定分區類型為字符串
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/student/input1'; #指定外部表路徑語句要放在最后一行
查看一下分區表的結構:
hive> desc students_pt1;
OK
id bigint
name string
age int
gender string
clazz string
pt string //多了額外的一列字段pt,專門作為分區的信息
# Partition Information
# col_name data_type comment
pt string
Time taken: 0.172 seconds, Fetched: 11 row(s)
增加一個分區:
alter table students_pt1 add partition(pt='20220216');
#增加一個分區,HDFS中在/student/input1目錄下,增加一個子目錄pt=20220218
alter table students_pt1 add partition(pt='20220217');
alter table students_pt1 add partition(pt='20220218');
alter table students_pt1 add partition(pt='20220219');
刪除一個分區
alter table students_pt1 drop partition(pt='20220216');
#此命令刪除的是子目錄pt=20220216的元數據,數據和目錄名不會刪掉,因為這是個外部表
#dfs -rmr /student/input1/pt=20220216;刪除的是子目錄的數據和目錄名,但是元數據不會刪除
查看某個表的所有分區
show partitions students_pt1; // 推薦這種方式(直接從元數據中獲取分區信息)
select distinct pt from students_pt; // 不推薦
往分區中插入數據
建立分區表后,加載數據必須加載到分區表下的分區(子目錄中);
insert into table students_pt1 select * from students;
像這樣直接插入外部表會報錯
#未創建分區前,也可以直接插入數據,不過插入的時候一定要加上partition(pt='20220218'),
#會自動創建子目錄pt=20220218,並將數據存在至該子目錄
#方法1:
insert into table students_pt1 partition(pt='20220218') select * from students;
#方法2:
load data local inpath '/usr/local/soft/data/students.txt' into table students_pt1 partition(pt='20220217');
查詢某個分區的數據
下面命令查詢的是分區數據有多少條記錄,執行結果是一個數字
// 全表掃描,不推薦,效率低
select count(*) from students_pt1;
// 使用where條件進行分區裁剪,避免了全表掃描,效率高
select count(*) from students_pt1 where pt='20220218';
// 也可以在where條件中使用非等值判斷
select count(*) from students_pt1 where pt<='20210112' and pt>='20210110';
查詢分區的數據
select * from students_pt1 where pt='20220220';
執行結果
hive> select * from students_pt1 where pt='20220220' limit 10;
OK
1500100001 施笑槐 22 女 文科六班 20220220
1500100002 呂金鵬 24 男 文科六班 20220220
1500100003 單樂蕊 22 女 理科六班 20220220
1500100004 葛德曜 24 男 理科三班 20220220
1500100005 宣谷芹 22 女 理科五班 20220220
1500100006 邊昂雄 21 男 理科二班 20220220
1500100007 尚孤風 23 女 文科六班 20220220
1500100008 符半雙 22 女 理科六班 20220220
1500100009 沈德昌 21 男 理科一班 20220220
1500100010 羿彥昌 23 男 理科六班 20220220
Time taken: 0.104 seconds, Fetched: 10 row(s)
//可見,最后面多了一列20220220,20220220就是分區表的分區字段
二、Hive動態分區
有的時候我們原始表中的數據里面包含了 ''日期字段 dt'',我們需要根據dt中不同的日期,
分為不同的分區,將原始表改造成分區表。
hive默認不開啟動態分區
動態分區:根據數據中某幾列的不同的取值 划分 不同的分區
1、開啟Hive的動態分區支持
# 表示開啟動態分區
hive> set hive.exec.dynamic.partition=true;
# 表示動態分區模式:strict(需要配合靜態分區一起使用)、nostrict
# strict: insert into table students_pt partition(dt='anhui',pt) select ......,pt from students;
#一般使用下面這個(一次性的,退出hive就沒了,還得重新開啟動態分區)
hive> set hive.exec.dynamic.partition.mode=nostrict;
# 表示支持的最大的分區數量為1000,可以根據業務自己調整
hive> set hive.exec.max.dynamic.partitions.pernode=1000;
2、建立原始表並加載數據(建立一個普通的表)
create table students_dt
(
id bigint,
name string,
age int,
gender string,
clazz string,
dt string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
將數據文件存放到本地/usr/local/soft/data/
並加載數據
將students_dt.txt文件拖至Xshell
加載數據到所創建的表中
load data local inpath '/usr/local/soft/data/students_dt.txt' into table students_dt;
3、建立分區表並加載數據
create table students_dt_p
(
id bigint,
name string,
age int,
gender string,
clazz string
)
PARTITIONED BY(dt string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
使用動態分區插入數據
#分區字段需要放在select的最后,如果有多個分區字段,同理,它是按位置匹配,不是按名字匹配
#動態分區插入數據的時候,要手動輸入字段名稱
insert into table students_dt_p partition(dt) select id,name,age,gender,clazz,dt from students_dt;
#比如下面這條語句會使用age作為分區字段,而不會使用student_dt中的dt作為分區字段
insert into table students_dt_p partition(dt) select id,name,age,gender,dt,age from students_dt;
4、多級分區(多級子目錄)
#建立常規表
create table students_year_month
(
id bigint,
name string,
age int,
gender string,
clazz string,
year string,
month string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
#建立分區表,分區字段為year,month
create table students_year_month_pt
(
id bigint,
name string,
age int,
gender string,
clazz string
)
PARTITIONED BY(year string,month string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
#將本地數據文件加載到常規表中
load data local inpath '/usr/local/soft/data/students_year_month.txt' into table students_year_month;
#將常規表中的數據加載到分區表進行分區
insert into table students_year_month_pt partition(year,month) select id,name,age,gender,clazz,year,month from students_year_month;
自己嘗試一下多級分區
上單講分區(阿里雲):https://developer.aliyun.com/article/81775