各位看官,今天我們來討論下再Hive中的動態分區和混合分區方面的一些知識點以及相關的一些問題。
前面我們已經講過管理表和外部表的一般分區的一些知識點,對於需要對表創建很多的分區,那么用戶就需要些很多的SQL代碼,舉例:
比如我創建了一張分區表emp,需要 將分區表employees中的某些區數據按分區導入到表emp中,如果我需要導入的分區有上百個,那么就需要寫上百個INSERT ...SELECT ...語句。如下:
FROM jimdb.employees
INSERT OVERWRITE TABLE emp
PARTITION(province='guangdong',city='shenzhen')
SELECT name,salary,subordinates,deductions,address
WHERE province='guangdong' AND city='shenzhen'
INSERT OVERWRITE TABLE emp
PARTITION(province='hainan',city='haikou')
SELECT name,salary,subordinates,deductions,address
WHERE province='hainan' AND city='haikou'
INSERT OVERWRITE TABLE emp
PARTITION(province='zhejiang',city='hangzhou')
SELECT name,salary,subordinates,deductions,address
WHERE province='zhejiang' AND city='hangzhou'
INSERT OVERWRITE TABLE emp
PARTITION(province='shandong',city='qingdao')
SELECT name,salary,subordinates,deductions,address
WHERE province='shandong' AND city='qingdao'
..........
..........
.........
一. Hive提供了一個動態分區的功能,其可以基於查詢參數推斷出需要創建的分區名稱。而之前我們一直使用的這種叫做靜態分區。
舉例1:假如我希望創建一張與employees表結構一樣的表emp,如何將employees的數據按分區導入到emp中呢。
hive (default)> CREATE TABLE IF NOT EXISTS emp LIKE jimdb.employees;
OK
Time taken: 2.387 seconds
為表emp中插入數據;
hive (default)> set hive.exec.dynamic.partition.mode=nostrict;
hive (default)> INSERT OVERWRITE TABLE emp
> PARTITION(province,city)
> SELECT name,salary,subordinates,deductions,address,province,city
> FROM jimdb.employees;
Query ID = hadoop_20180617092034_4fd7e0ee-0916-4b85-91e1-1d569110c3e7
.........
........
Stage-Stage-1: HDFS Read: 30511582 HDFS Write: 31358028 SUCCESS
Total MapReduce CPU Time Spent: 0 msec
OK
name salary subordinates deductions address province city
Time taken: 16.077 seconds
Hive是根據select語句最后的兩個列來確定分區字段province,city的值。目標表的分區字段名稱可以與源表的分區字段名稱不一樣。
二.混合分區
由於在動態分區中目標表的分區是根據源表的分區字段的值來確定的,如果由於用戶錯誤的操作,導致目標表創建了非常多的小分區,這會導致集群性能的下降,因為管理分區是需要HDFS 的namenode進行管理。如果存在非常多的分區,那么最終會超出NameNode對系統雲數據信息的處理能力。因為NameNode必須要將所有的系統文件的元數據信息保存在內存中。理想的分區方案是不應該導致太多的分區和文件夾目錄,並且每個目錄下的文件應該足夠得大,應該是文件系統中塊的若干倍。
混合分區就是混合使用靜態分區和動態分區來創建目標表的分區,但是靜態分區的字段必須放到動態分區字段的前面。由於混合分區部分的限制了分區的 鍵的值,可以有效 控制分區的數目不會過多,從而錯誤的導致創建很多的分區。
比如我希望給emp表中加入shandong與zhejiang兩個省份的數據,可以使用如下的混合分區的方法進行數據的導入:
hive (default)> FROM jimdb.employees
> INSERT OVERWRITE TABLE emp
> PARTITION(province='shandong',city)
> SELECT name,salary,subordinates,deductions,address,city
> WHERE province ='guangdong'
> INSERT OVERWRITE TABLE emp
> PARTITION(province='zhejiang',city)
> SELECT name,salary,subordinates,deductions,address,city
> WHERE province ='zhejiang';
Query ID = hadoop_20180617094311_8a38bc83-a6cb-40a9-87d5-f4c4f66364d2
Total MapReduce CPU Time Spent: 0 msec
.........
.........
OK
name salary subordinates deductions address city
Time taken: 11.95 seconds
可以看到一個規律,就是說在目標表中對分區中限定值得靜態分區鍵的那一列,目標表就就認為這一列不屬於需要插入的列值,因此在select語句中需要將這一列去除掉,不然就會報錯。比如我限定了province='shandong',那么select選擇的列中就取出掉province這一列。如下面這種方法就會報錯:
hive (default)>
> INSERT OVERWRITE TABLE emp
> PARTITION(province='guangdong',city)
> SELECT name,salary,subordinates,deductions,address,province,city
> FROM jimdb.employees
> WHERE province ='guangdong';
FAILED: SemanticException [Error 10044]: Line 1:23 Cannot insert into target table because column number/types are different 'city': Table insclause-0 has 6 columns, but query has 7 columns.
hive (default)> INSERT OVERWRITE TABLE emp
> PARTITION(province='guangdong',city)
> SELECT *
> FROM jimdb.employees
> WHERE province ='guangdong';
FAILED: SemanticException [Error 10044]: Line 1:23 Cannot insert into target table because column number/types are different 'city': Table insclause-0 has 6 columns, but query has 7 columns.
這兩個語句都是同樣的錯誤,目標表emp由於在分區上限定了province,因此在插入數據時,不將這一列作為偽列看待,因此只有6列,而select語句中顯式的將兩個分區鍵放到最后,或者select * 都會將分區鍵放到正常列的最后面,這樣就會存在7個列,因此插入數據時報錯。
三.動態分區的相關參數
在Hive中,針對動態分區有幾個參數需要注意。
1.hive.exec.dynamic.partition,這個參數是開啟動態分區功能,默認是false不開啟。
2. hive.exec.dynamic.partition.mode 這個參數是動態分區模式,缺省值是strict,表示動態分區前面必須有靜態分區字段,不能只有動態分區,可以設置為nostrict,表示允許所有分區都是動態的。
3. hive.exec.dynamic.partitions.pernode ,缺省值是100,指每個mapper或reducer可以創建的最大動態分區個數,如果某個mapper或者reducerchangshi 創建大於這個數目的分區,那么就會報錯。
4. hive.exec.max.dynamic.partitions 缺省值是+1000,指的是一個動態分區創建語句可以創建的最大分區數目,如果超過這個數目就會拋出一個致命錯誤。
5. hive.exec.max.created.files 缺省值是100000,全局 可以創建的最大文件個數。
四.當動態分區模式是strict時,如果創建動態分區,會拋出錯誤。
hive (default)> set hive.exec.dynamic.partition.mode=strict;
hive (default)> INSERT OVERWRITE TABLE emp
> PARTITION(province,city)
> SELECT name,salary,subordinates,deductions,address,province,city
> FROM jimdb.employees;
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
