Hive動態分區詳解,你知道嗎?
本文轉載自微信公眾號「Java大數據與數據倉庫」,作者柯同學。轉載本文請聯系Java大數據與數據倉庫公眾號。
動態分區調整
- 動態分區屬性:設置為true表示開啟動態分區功能(默認為false)hive.exec.dynamic.partition=true;
- 動態分區屬性:設置為nonstrict,表示允許所有分區都是動態的(默認為strict)設置為strict,表示必須保證至少有一個分區是靜態的hive.exec.dynamic.partition.mode=strict;
- 動態分區屬性:每個mapper或reducer可以創建的最大動態分區個數hive.exec.max.dynamic.partitions.pernode=100;
- 動態分區屬性:一個動態分區創建語句可以創建的最大動態分區個數hive.exec.max.dynamic.partitions=1000;
- 動態分區屬性:全局可以創建的最大文件個數hive.exec.max.created.files=100000;
- 控制DataNode一次可以打開的文件個數 這個參數必須設置在DataNode的$HADOOP_HOME/conf/hdfs-site.xml文件中
- <property>
- <name>dfs.datanode.max.xcievers</name>
- <value>8192</value>
- </property>
注意
在Hive中,動態分區會造成在插入數據過程中,生成過多零碎的小文件
動態分區插入
如果需要創建非常多的分區,用戶就需要寫非常多的條件查詢sql把數據插入對應分區。好在Hive提供了動態分區功能,可以根據分區字段的取值自動創建分區。前面列出的開啟動態分區hive.exec.dynamic.partition,并且hive.exec.dynamic.partition.mode需要為非嚴格模式,通常如果分區很多的話,hive.exec.max.dynamic.partitions.pernode也需要設置為一個較大的數,否則會有報錯提醒。
現在有sql:
- insert overwrite table employees partitions (country, state)
- select ...,se.cnty, se.st
- from staged_employees se;
可以看出,Hive根據select語句中最后兩列來確定分區字段country和state的值,這里刻意使用了不同的命名,就是為了強調源表字段和輸出分區值之間的關系是根據位置而不是根據命名來匹配的。
動靜分區結合
也可以混合使用動態和靜態分區。上面那個例子,我們可以指定國家這個分區值五為靜態值US,而分區字段state是動態值:
- insert overwrite table employees partitions (country = 'US', state)
- select ...,se.cnty, se.st
- from staged_employees se
- where se.cnty = 'US';
注意:靜態分區需要出現在動態分區字段之前。
動態分區功能默認情況下是沒有開啟的,默認是以嚴格模式執行,這種模式下要求至少有一列分區字段是靜態的。這樣做的好處是可以防止因設計或其它錯誤查詢導致產生大量的分區,比如sql boy不小心使用了時間戳作為分區字段,那將是災難。在日常導入一天的數據,通常是指定日期為靜態分區,小時為動態分區,進行混合模式導入。
例子
建表
- create table if not exists test.test
- (
- id string,
- name string
- )
- partitioned by (dt string,hour string)
- row format delimited fields terminated by '\t';
- create table if not exists test.test2
- (
- id string,
- name string
- )
- partitioned by (dt string,hour string)
- row format delimited fields terminated by '\t'
- stored as orc;
導入數據到test.test表
- load data local inpath '/home/hadoop/data/test.txt' into table test.test partition(dt = '2019-09-10', hour = '02');
- test.txt
- 001 keguang
- 002 kg
- 003 kk
- 004 ikeguang
利用動態分區插入
- insert overwrite table test.test2 partition(dt, hour) select `(dt|hour)?+.+`,dt,hour from test.test;
這里,(dt|hour)?+.+表示查詢出test表除了dt和hour這兩個字段的其它所有字段。