pypark hive 开启动态分区_Hive分区与分桶
分區(qū)、分桶的作用:
我們知道在傳統(tǒng)的DBMs系統(tǒng)中,一般都具有表分區(qū)的功能,通過表分區(qū)能夠在特定的區(qū)域檢索數(shù)據(jù),減少掃描成本,在一定程度上提高了查詢效率,當(dāng)然我們還可以通過進(jìn)一步在分區(qū)上建立索引,進(jìn)一步提高查詢效率。
在Hive中的數(shù)據(jù)倉庫中,也有分區(qū)分桶的概念,在邏輯上,分區(qū)表與未分區(qū)表沒有區(qū)別,在物理上分區(qū)表會將數(shù)據(jù)按照分區(qū)間的列值存儲在表目錄的子目錄中,目錄名=“分區(qū)鍵=鍵值”。其中需要注意的是分區(qū)鍵的列值存儲在表目錄的子目錄中,目錄名=“分區(qū)鍵=鍵值”。其中需要注意的是分區(qū)鍵的值不一定要基于表的某一列(字段),它可以指定任意值,只要查詢的時候指定相應(yīng)的分區(qū)鍵來查詢即可。我們可以對分區(qū)進(jìn)行添加、刪除、重命名、清空等操作。
分桶則是指定分桶表的某一列,讓該列數(shù)據(jù)按照哈希取模的方式隨機(jī)、均勻的分發(fā)到各個桶文件中。因為分桶操作需要根據(jù)某一列具體數(shù)據(jù)來進(jìn)行哈希取模操作,故指定的分桶列必須基于表中的某一列(字段)。分桶改變了數(shù)據(jù)的存儲方式,它會把哈希取模相同或者在某一個區(qū)間的數(shù)據(jù)行放在同一個桶文件中。如此一來便可以提高查詢效率。如果我們需要對兩張在同一個列上進(jìn)行了分桶操作的表進(jìn)行JOIN操作的時候,只需要對保存相同列值的通進(jìn)行JOIN操作即可。
還有一點需要點一下:在hive中的數(shù)據(jù)是存儲在hdfs中的,我們知道hdfs中的數(shù)據(jù)是不允許修改只能追加的,那么在hive中執(zhí)行數(shù)據(jù)修改的命令時,就只能先找到對應(yīng)的文件,讀取后執(zhí)行修改操作,然后重新寫一份文件。如果文件比較大,就需要大量的IO讀寫。在hive中采用了分桶的策略,只需要找到文件存放對應(yīng)的桶,然后讀取再修改寫入即可。
分區(qū):
hive中分區(qū)分為 : 單值分區(qū)、范圍分區(qū)。
單值分區(qū): 靜態(tài)分區(qū) 動態(tài)分區(qū)
如下所示,現(xiàn)在有一張persionrank表,記錄每個人的評級,有id、name、score字段。我們可以創(chuàng)建分區(qū)rank(rank不是表中的列,我們可以把它當(dāng)做虛擬列),并將相應(yīng)的數(shù)據(jù)導(dǎo)入指定分區(qū)(將數(shù)據(jù)插入指定目錄)。
單值分區(qū):
單值靜態(tài)分區(qū):導(dǎo)入數(shù)據(jù)時需要手動指定分區(qū)
單值動態(tài)分區(qū):導(dǎo)入數(shù)據(jù)時,系統(tǒng)可以動態(tài)判斷目標(biāo)分區(qū)
1.靜態(tài)分區(qū)創(chuàng)建:
直接在PARTITI1ONED BY后面跟上分區(qū)鍵、類型即可(指定的分區(qū)鍵不能出現(xiàn)在定義列名中)
CREATE [EXTERNAL] TABLE <table_name>(<col_name> <data_type> [, <col_name> <data_type> ...])-- 指定分區(qū)鍵和數(shù)據(jù)類型PARTITIONED BY (<partition_key> <data_type>, ...) [CLUSTERED BY ...] [ROW FORMAT <row_format>] [STORED AS TEXTFILE|ORC|CSVFILE][LOCATION '<file_path>'] [TBLPROPERTIES ('<property_name>'='<property_value>', ...)];2.靜態(tài)分區(qū)寫入:
-- 覆蓋寫入 INSERT OVERWRITE TABLE <table_name> PARTITION (<partition_key>=<partition_value>[, <partition_key>=<partition_value>, ...]) SELECT <select_statement>;-- 追加寫入 INSERT INTO TABLE <table_name> PARTITION (<partition_key>=<partition_value>[, <partition_key>=<partition_value>, ...])SELECT <select_statement>;3.添加分區(qū):
//只能添加分區(qū)列的值,不能添加分區(qū)列,如果是多個分區(qū)列,不能單獨(dú)添加其中一個 alter table tablename add partition(col=value)4.刪除分區(qū):
//可以刪除一個分區(qū)列,但是會把表中所有包含當(dāng)前分區(qū)列的數(shù)據(jù)全部刪除 alter table tablename drop partition(col=value)5.修復(fù)分區(qū):
//手動向hdfs中創(chuàng)建分區(qū)目錄,添加數(shù)據(jù),創(chuàng)建好hive的外表之后,無法加載數(shù)據(jù), //元數(shù)據(jù)中沒有相應(yīng)的記錄 msck repair table tablename6.動態(tài)分區(qū)創(chuàng)建:
創(chuàng)建方式與靜態(tài)分區(qū)表完全一樣,一張表可同時被靜態(tài)分區(qū)和動態(tài)分區(qū)鍵分區(qū),只是動態(tài)分區(qū)鍵需要放在靜態(tài)分區(qū)鍵的后面(HDFS上的動態(tài)分區(qū)目錄下不能包含靜態(tài)分區(qū)的子目錄),如下spk即static partition key(靜態(tài)分區(qū)鍵),dpk為dynamic partition key(動態(tài)分區(qū)鍵)
CREATE TABLE <table_name>PARTITIONED BY ([<spk> <data_type>, ... ,] <dpk> <data_type>, [<dpk> <data_type>,...]);7.動態(tài)分區(qū)寫入:
根據(jù)表中的某一個列值來確定hdfs存儲的目錄:
優(yōu)點:
動態(tài)可變,不需要人為控制。假如設(shè)定的是日期,那么每一天的數(shù)據(jù)會單獨(dú)存儲在一個文件夾中
缺點:
需要依靠MR完成,執(zhí)行比較慢
靜態(tài)分區(qū)鍵要用 <spk>=<value> 指定分區(qū)值;動態(tài)分區(qū)只需要給出分出分區(qū)鍵名稱 <dpk>。
-- 開啟動態(tài)分區(qū)支持,并設(shè)置最大分區(qū)數(shù) set hive.exec.dynamic.partition=true; //set hive.exec.dynamic.partition.mode=nostrict; set hive.exec.max.dynamic.partitions=2000;insert into table1 select 普通字段 分區(qū)字段 from table2范圍分區(qū):
單值分區(qū)每個分區(qū)對應(yīng)于分區(qū)鍵的一個取值,而每個范圍分區(qū)則對應(yīng)分區(qū)鍵的一個區(qū)間,只要落在指定區(qū)間內(nèi)的記錄都被存儲在對應(yīng)的分區(qū)下。分區(qū)范圍需要手動指定,分區(qū)的范圍為前閉后開區(qū)間 [最小值, 最大值)。最后出現(xiàn)的分區(qū)可以使用 MAXVALUE 作為上限,MAXVALUE 代表該分區(qū)鍵的數(shù)據(jù)類型所允許的最大值。
CREATE [EXTERNAL] TABLE <table_name>(<col_name> <data_type>, <col_name> <data_type>, ...)PARTITIONED BY RANGE (<partition_key> <data_type>, ...) (PARTITION [<partition_name>] VALUES LESS THAN (<cutoff>), [PARTITION [<partition_name>] VALUES LESS THAN (<cutoff>),...]PARTITION [<partition_name>] VALUES LESS THAN (<cutoff>|MAXVALUE) )[ROW FORMAT <row_format>] [STORED AS TEXTFILE|ORC|CSVFILE][LOCATION '<file_path>'] [TBLPROPERTIES ('<property_name>'='<property_value>', ...)];多個范圍分區(qū)鍵的情況:
DROP TABLE IF EXISTS test_demo; CREATE TABLE test_demo (value INT) PARTITIONED BY RANGE (id1 INT, id2 INT, id3 INT) ( -- id1在(--∞,5]之間,id2在(-∞,105]之間,id3在(-∞,205]之間 PARTITION p5_105_205 VALUES LESS THAN (5, 105, 205), -- id1在(--∞,5]之間,id2在(-∞,105]之間,id3在(205,215]之間 PARTITION p5_105_215 VALUES LESS THAN (5, 105, 215), PARTITION p5_115_max VALUES LESS THAN (5, 115, MAXVALUE), PARTITION p10_115_205 VALUES LESS THAN (10, 115, 205), PARTITION p10_115_215 VALUES LESS THAN (10, 115, 215), PARTITION pall_max values less than (MAXVALUE, MAXVALUE, MAXVALUE) );分桶:
對Hive(Inceptor)表分桶可以將表中記錄按分桶鍵的哈希值分散進(jìn)多個文件中,這些小文件稱為桶。
1.創(chuàng)建分桶表:
分桶表的建表有三種方式:直接建表,CREATE TABLE LIKE 和 CREATE TABLE AS SELECT ,單值分區(qū)表不能用 CREATE TABLE AS SELECT 建表。這里以直接建表為例:
CREATE [EXTERNAL] TABLE <table_name>(<col_name> <data_type> [, <col_name> <data_type> ...])][PARTITIONED BY ...] CLUSTERED BY (<col_name>) [SORTED BY (<col_name> [ASC|DESC] [, <col_name> [ASC|DESC]...])] INTO <num_buckets> BUCKETS [ROW FORMAT <row_format>] [STORED AS TEXTFILE|ORC|CSVFILE][LOCATION '<file_path>'] [TBLPROPERTIES ('<property_name>'='<property_value>', ...)];分桶鍵只能有一個即<col_name>。表可以同時分區(qū)和分桶,當(dāng)表分區(qū)時,每個分區(qū)下都會有<num_buckets> 個桶。我們也可以選擇使用 SORTED BY … 在桶內(nèi)排序,排序鍵和分桶鍵無需相同。ASC 為升序選項,DESC 為降序選項,默認(rèn)排序方式是升序。<num_buckets> 指定分桶個數(shù),也就是表目錄下小文件的個數(shù)。
2.向分桶表中寫數(shù)據(jù):
因為分桶表在創(chuàng)建的時候只會定義Scheme,且寫入數(shù)據(jù)的時候不會自動進(jìn)行分桶、排序,需要人工先進(jìn)行分桶、排序后再寫入數(shù)據(jù)。確保目標(biāo)表中的數(shù)據(jù)和它定義的分布一致。
目前有兩種方式往分桶表中插入數(shù)據(jù):
方法一:打開enforce bucketing開關(guān)。
SET hive.enforce.bucketing=true; INSERT (INTO|OVERWRITE) TABLE <bucketed_table> SELECT <select_statement> [SORT BY <sort_key> [ASC|DESC], [<sort_key> [ASC|DESC], ...]];方法二:將reducer個數(shù)設(shè)置為目標(biāo)表的桶數(shù),并在 SELECT 語句中用 DISTRIBUTE BY <bucket_key>對查詢結(jié)果按目標(biāo)表的分桶鍵分進(jìn)reducer中。
SET mapred.reduce.tasks = <num_buckets>; INSERT (INTO|OVERWRITE) TABLE <bucketed_table> SELECT <select_statement> DISTRIBUTE BY <bucket_key>, [<bucket_key>, ...] [SORT BY <sort_key> [ASC|DESC], [<sort_key> [ASC|DESC], ...]];如果分桶表創(chuàng)建時定義了排序鍵,那么數(shù)據(jù)不僅要分桶,還要排序
如果分桶鍵和排序鍵不同,且按降序排列,使用Distribute by … Sort by分桶排序
如果分桶鍵和排序鍵相同,且按升序排列(默認(rèn)),使用 Cluster by 分桶排序,即如下:
SET mapred.reduce.tasks = <num_buckets>; INSERT (INTO|OVERWRITE) TABLE <bucketed_table> SELECT <select_statement> CLUSTER BY <bucket_sort_key>, [<bucket_sort_key>, ...];抽樣語句 :tablesample(bucket x out of y)
tablesample是抽樣語句,語法:tablesample(bucket x out of y),y必須是table總共bucket數(shù)的倍數(shù)或者因子。Hive根據(jù)y的大小,決定抽樣的比例。例如:table總共分了64份,當(dāng)y=32時,抽取2(64/32)個bucket的數(shù)據(jù),當(dāng)y=128時,抽取1/2(64/128)個bucket的數(shù)據(jù)。x表示從哪個bucket開始抽取。例如:table總共bucket數(shù)為32,tablesample(bucket 3 out of 16)表示總共抽取2(32/16)個bucket的數(shù)據(jù),分別為第三個bucket和第19(3+16)個bucket的數(shù)據(jù)。
總結(jié)
以上是生活随笔為你收集整理的pypark hive 开启动态分区_Hive分区与分桶的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css使两个盒子并列_css如何去掉重叠
- 下一篇: unity双面显示在哪_双面屏努比亚Z2