Hive分桶之BUCKET詳解


參考:https://www.jianshu.com/p/9075ccd0bfba

Bucket

1.對於每一個表(table)或者分區(partition), Hive可以進一步組織成桶,也就是說桶是更為細粒度的數據范圍划分。Hive也是 針對某一列進行桶的組織。Hive采用對列值哈希,然后除以桶的個數求余的方式決定該條記錄存放在哪個桶當中。

2,把表(或者分區)組織成桶(Bucket)有兩個理由:
*(1)獲得更高的查詢處理效率。桶為表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,連接兩個在(包含連接列的)相同列上划分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實現。比如JOIN操作。對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那么將保存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的數據量。
*(2)使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,如果能在數據集的一小部分數據上試運行查詢,會帶來很多方便。
下面來一個例子:

Create table dz_test( id bigint comment’編號’,(ps:comment為注釋) name string comment’姓名’ )comment’編號與姓名表’ Partitioned by(pdate string) Clustered by(id) 按id分桶,自動哈希分桶 Sorted by(id) 按id排序 Into 4 buckets 分成4個桶 Row format delimited 設置創建的表在加載數據的時候,支持的列分隔符 Fields terminated by ‘\t’ 每個字段按\t分割 Lines terminated by’\n’ stored as textfile; 按\n為斷行符,指定導入的文件為純文本。 //Hive本身支持的文件格式只有:Text File,Sequence File,如果數據需要壓縮,使用 //[STORED AS SEQUENCE] 

下面load數據:
插入數據之前需要設置參數hive.enforce.bucketing=true,以強制hive的reducer數目為分桶數。如果不設置這個hive參數,最后的桶個數可能不是建表語句中的個數。另外,也可以通過將參數mapred.reduce.tasks設置為桶的數目來控制reducer的數目,建議采用第一種方式。

Set hive.enforce.bucketing=true;
Load data local inpath’/home/Hadoop/….’ overwrite into table dz_test partition(pdate=‘2015-10’)

物理上,每個桶就是表(或分區)目錄里的一個文件。它的文件名並不重要,但是桶 n 是按照字典序排列的第 n 個文件。事實上,桶對應於 MapReduce 的輸出文件分區:一個作業產生的桶(輸出文件)和reduce任務個數相同。

我們可以通過查看剛才 創建的bucketd_users表的布局來了解這一情況。運行如下命令:

查看表的結構:
hive> dfs -ls /user/hive/warehouse/dz_test; 
將顯示有4個新建的文件。文件名如下(文件名包含時間戳,由Hive產生,因此 每次運行都會改變): 
attempt_201701221636_0016_r_000000_0 
attempt_201701221636_0016_r-000001_0 
attempt_201701221636_0016_r_000002_0 
attempt_201701221636_0016_r_000003_0 
第一個桶里包括用戶ID和4,因為一個INT的哈希值就是這個整數本身,在這里 除以桶數(4)以后的余數:2
讀取數據,看每一個文件的數據:
hive> dfs -cat /user/hive/warehouse/dz_test/*0_0; 
0 Nat 
4 Ann 
用TABLESAMPLE子句對表進行取樣,我們可以獲得相同的結果。這個子句會將 查詢限定在表的一部分桶內,而不是使用整個表:
. 對桶中的數據進行采樣:
hive> SELECT * FROM dz_test 
>TABLESAMPLE(BUCKET 1 OUT OF 4 ON id); 
0 Nat 
4 Ann 
桶的個數從1開始計數。因此,前面的查詢從4個桶的第一個中獲取所有的用戶。 對於一個大規模的、均勻分布的數據集,這會返回表中約四分之一的數據行。我們 也可以用其他比例對若干個桶進行取樣(因為取樣並不是一個精確的操作,因此這個 比例不一定要是桶數的整數倍)。例如,下面的查詢返回一半的桶:
7. 查詢一半返回的桶數:
hive> SELECT * FROM dz_test 
>    TABLESAMPLE(BUCKET 1 OUT OF 2 ON id); 
0 Nat 
4 Ann 
2 Joe 
因為查詢只需要讀取和TABLESAMPLE子句匹配的桶,所以取樣分桶表是非常高效 的操作。如果使用rand()函數對沒有划分成桶的表進行取樣,即使只需要讀取很 小一部分樣本,也要掃描整個輸入數據集: 
hive〉 SELECT * FROM dz_test 
> TABLESAMPLE(BUCKET 1 OUT OF 4 ON rand()); 
2 Doe 
①從Hive 0.6.0開始,對以前的版本,必須把mapred.reduce .tasks設為表中要填 充的桶的個數。如果桶是排序的,還需要把hive.enforce.sorting設為true。 
②顯式原始文件時,因為分隔字符是一個不能打印的控制字符,因此字段都擠在一起。 

https://blog.csdn.net/m0_37534613/article/details/55258928

總結:在Join兩邊的時候使用到view,這樣可以使用分桶的概念,優化Join的性能。



作者:丹之
鏈接:https://www.jianshu.com/p/9075ccd0bfba
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM