面試官問我,什么是hive的靜態磁區和動態磁區,這題我會呀,
簡述
磁區是hive存放資料的一種方式,將列值作為目錄來存放資料,就是一個磁區,可以有多列,
這樣查詢時使用磁區列進行過濾,只需根據列值直接掃描對應目錄下的資料,不掃描不關心的磁區,快速定位,提高查詢效率,
hive的磁區有兩種型別:
- 靜態磁區SP(Static Partitioning)
- 動態磁區DP(Dynamic Partitioning)
對于靜態磁區,表的磁區數量和磁區值是固定的,新增磁區或者是加載磁區資料時,需要提前指定磁區名,
對于動態磁區,磁區的值是不確定的,會根據資料自動的創建新的磁區,
一、靜態磁區
如上所述,靜態磁區的使用場景主要是磁區的數量是確定的,例如日志流水資料中使用日期作為磁區欄位,通常在寫入之前就已經確定了是哪個磁區,
1.單磁區建表
create table if not exists day_log(
uid bigint,
uname string,
action string
) comment '用戶動作流水記錄'
partitioned by(ymd string comment '日期格式yyyyMMdd')
row format delimited fields terminated by '\t';
2.加載資料到指定磁區
load data local inpath '/user/hive/data/day_log.txt'
into table day_log paritition(ymd='20220803')
3.創建具有多個磁區的表
create table if not exists day_log(
uid bigint,
uname string,
action string
) comment '用戶動作流水記錄'
partitioned by(year string,month string,day string)
row format delimited fields terminated by '\t';
4.加載資料
load data local inpath '/user/hive/data/day_log.txt'
into table day_log paritition(year='2022',month='08',day='02')
但通常我們寫入磁區資料是通過計算SQL結果直接寫入,并不是從外部檔案load進來的,示例如下:
insert overwrite table day_log partition (year='2022',month='08',day='02')
select uid,uname,action from (
xxxxxx
)
二、動態磁區
所謂動態磁區,磁區的值是不確定的,磁區的數量是不確定,皆由加載資料確定,
生產環境中,動態磁區一般常用于創建新表后,需要一次性加載歷史資料,
1.創建臨時表
-- 創建臨時表
create table if not exists tmp (
uid int,
commentid bigint,
recommentid bigint,
year int,
month int,
day int
)
row format delimited fields terminated by '\t';
-- 加載資料到臨時表
load data local inpath 'user/hive/data/tmp.txt' into table tmp;
2.創建動態磁區表
-- 創建動態磁區表
create table if not exists dp_tmp(
uid int,
commentid bigint,
recommentid bigint
)
partitioned by (year string,month string,day string)
row format delimited fields terminated by '\t';
-- 寫入資料到磁區表
-- 引數為開啟動態磁區
set hive.exec.dynamic.partition=true;
insert overwrite table dp_tmp partition(year,month,day)
select uid,commentid,recommentid,year,month,day from tmp;
執行上述寫入陳述句會報錯:
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
看報錯資訊:動態磁區嚴格模式至少需要一個靜態磁區列,關閉它,設定引數
set hive.exec.dynamic.partition.mode=nonstrict
下文介紹hive相關引數作用
3.嚴格模式
引數hive.exec.dynamic.partition.mode表示動態磁區的模式,
默認是strict,也就是嚴格模式,表示必須指定至少一個磁區為靜態磁區
nonstrict模式,即非嚴格模式,表示允許所有的磁區欄位都可以使用動態磁區
嚴格模式
-- 至少需要指定一個靜態磁區列
-- 開啟動態磁區
set hive.exec.dynamic.partition=true;
insert overwrite table dp_tmp partition(year='2022',month,day)
select uid,commentid,recommentid,month,day from tmp;
4.非嚴格模式
set hive.exec.dynamic.partition=true;
-- 允許所有的磁區欄位都可以使用動態磁區,兼容嚴格模式
-- 更改動態磁區模式為非嚴格模式
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table dp_tmp partition(year,month,day)
select uid,commentid,recommentid,month,day from tmp;
通常情況下,我們使用動態磁區,為非嚴格模式:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
三、靜態磁區和動態磁區的區別
兩種磁區模式根據定義就可看出來明顯區別,這里單列一下:
| 靜態磁區(Static Partitioning) | 動態磁區(Dynamic Partitioning) | |
|---|---|---|
| 磁區創建 | 資料插入磁區之前,需要手動指定創建每個磁區 | 根據表的輸入資料動態創建磁區 |
| 適用場景 | 需要提前知道所有磁區,適用于磁區定義得早且數量少的用例,常見為插入某一個指定磁區 | 有很多磁區,無法提前預估新磁區,動態磁區是合適的 |
另外動態磁區的值是MapReduce任務在reduce運行階段確定的,也就是所有的記錄都會distribute by,相同欄位(磁區欄位)的map輸出會發到同一個reduce節點去處理,如果資料量大,這是一個很弱的運行性能,
而靜態磁區在編譯階段就確定了,不需要reduce任務處理,所以如果實際業務場景靜態磁區能解決的,盡量使用靜態磁區即可,
四、磁區使用注意事項
1.hive磁區引數及作用
hive表中的磁區作用主要是使資料按照磁區目錄存盤在hdfs上,查詢只要針對指定的目錄集合進行查詢,避免全域查找,這樣提高了查詢性能,
hive的磁區需要合理使用,過多的磁區目錄和檔案對于集群Namenode服務是有性能壓力的,Namenode需要將大量的元資料資訊保存在記憶體中,如果報錯,會造成Namenode不可用,
一次查詢表里有太多磁區,會使得查詢檔案過大,也會造成Metastore服務出現OOM報錯,報錯資訊顯示Metastore不可用,
hive為了避免因為例外產生大量磁區,導致上述問題,本身是默認動態磁區關閉,同時對生成動態磁區的數量也做了一定限制,
通過手動引數設定可以改變系統默認值,具體hive默認引數以及SQL執行配置引數(不同版本默認引數有一定差異)如下:
-- Hive默認配置值
-- 開啟或關閉動態磁區
hive.exec.dynamic.partition=false;
-- 設定為nonstrict模式,讓所有磁區都動態配置,否則至少需要指定一個磁區值
hive.exec.dynamic.partition.mode=strict;
-- 能被mapper或reducer創建的最大動態磁區數,超出而報錯
hive.exec.max.dynamic.partitions.pernode=100;
-- 一條帶有動態磁區SQL陳述句所能創建的最大動態磁區總數,超過則報錯
hive.exec.max.dynamic.partitions=1000;
-- 全域能被創建檔案數目的最大值,通過Hadoop計數器跟蹤,若超過則報錯
hive.exec.max.created.files=100000;
-- 根據個人需要配置
-- 設定動態磁區開啟
set hive.exec.dynamic.partition=true;
-- 設定為非嚴格模式
set hive.exec.dynamic.partition.mode=nonstrict;
-- 設定每個節點創建最大磁區數
set hive.exec.max.dynamic.partitions.pernode=1000;
-- 設定執行SQL創建最大磁區數
set hive.exec.max.dynamic.partitions=10000;
-- 設定全域被創建檔案最大值
set hive.exec.max.created.files=1000000;
在執行hiveSQL的時候如果動態磁區數量或檔案數任何一個超過集群默認就會產生報錯:
ERROR [LocalJobRunner Map Task Executor #0]:mr.ExecMapper (ExecMapper.java:map(171)) - org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row ....
Caused by: org.apache.hadoop.hive.ql.metadata.HiveFatalException: [Error 20004]: Fatal error occurred when node tried to create too many dynamic partitions. The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode. Maximum was set to: 256... 10 more
集群會kill任務,為了解決報錯,我們通常將三個引數調大,但是也需要用戶對自己的Hive表的磁區數量進行合理規劃,避免過多的磁區,
2.磁區常見注意事項
a. 盡量不要使用動態磁區,因為動態磁區的時候,將會為每一個磁區分配reducer數量,當磁區數量多的時候,reducer數量將會增加,對服務器是一種災難,
b. 動態磁區和靜態磁區的區別,靜態磁區不管有沒有資料都會創建指定磁區,動態磁區是有結果集將創建,否則不創建,
c. hive動態磁區的嚴格模式和hive嚴格模式是不同的,
hive提供的嚴格模式簡述:
hive提供的嚴格模式,為了組織用戶不小心提交惡意SQL
hive.mapred.mode=nostrict : strict
如果該模式值為strict,將會阻止一下三種查詢:
a.對磁區表查詢,where條件中過濾欄位沒有磁區欄位;
b.笛卡爾積join查詢,join查詢陳述句中不帶on條件或者where條件;
c.對order by查詢,有order by的查詢不太limit陳述句,
3.一些例外磁區處理
a.默認磁區
如果動態磁區列輸入的值為NULL或空字串,則hive將該行放入一個特殊磁區,磁區名稱由引數hive.exec.default.partition.name控制,
默認值為__HIVE_DEFAULT_PARTITION__,可以通過查看表磁區命令進行查看:
show partitions 'table';
-- ymd=__HIVE_DEFAULT_PARTITION__
清理該磁區使用正常洗掉磁區陳述句即可,對磁區的操作命令詳見上篇文章,
b.亂碼磁區
表磁區欄位處理不當可能會造成亂碼磁區,主要是由于轉譯編碼原因造成,例如:
sp_test=r_ready%3D91;r_load%3D351
原因是Hive會自動對一些UTF-8字符編碼成Unicode(類似網址中中文字符和一些特殊字符的編碼處理),此處%3D解碼后是'=',可以使用在線轉換進行解碼:https://www.matools.com/code-convert-utf8,
最后使用解碼后的欄位即可(注意分號轉義):
alter table dpdw_traffic_base drop partition(sp_test='r_ready=91\;r_load=351');
上一篇:關于hive磁區,你知道多少呢?
按例,我的個人公眾號:魯邊社,歡迎關注

后臺回復關鍵字 hive,隨機贈送一本魯邊備注版珍藏大資料書籍,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/501224.html
標籤:其他
