Hive的分桶表


【分桶概述】

  Hive表 分區的實質是 分目錄(將超大表的數據按指定標准細分到指定目錄),且分區的字段不屬於Hive表中存在的字段; 分桶的實質是 分文件(將超大文件的數據按指定標准細分到分桶文件),且分桶的字段必須在Hive表中存在。
 
  分桶的意義在於:
    1. 可以提高多表join的效率(因為通過分桶已經將超大數據集提取出來了。假如原數據被分了4個桶,此時2表join的時候只需要讀取符合條件的一個分桶,則理論上效率可提升4倍)
    2. 加速數據抽樣的效率(理由同上,只需要按照指定規則抽取指定分桶的數據即可,不需要掃描全表)
 
  需要Hive表分桶的時候,我們可以觀察到Reduce的任務數量 = 分桶的數量,也就是最終產生的分桶文件的個數,因為分桶表就是通過MapReduce任務計算而來。由此可見,其實桶的概念就是MapReduce的分區的概念,兩者完全相同。
  需要注意的是,不論每次插入分桶表的數據量有多少,對應分桶里面是否需要寫入新的數據,Reduce總會啟動分桶數量那么多的task去計算,故可能產生許多空白文件(原因是reduce寫的時候,不知道會不會有數據需要輸出,所以默認初始化了一個文件)。
  為了避免產生大量空白文件,給namenode增加無謂的壓力,我們可以通過以下設置方法告知reduce作業不要產生空白文件:
//導入jar包
import org.apache.hadoop.mapreduce.lib.output.LazyOutputFormat;
//使用LazyOutputFormat
LazyOutputFormat.setOutputFormatClass(job, TextOutputFormat.class);

 

  分桶表取樣語法的核心:
select * from tableName tablesample(bucket x out of y on colum)。其中:
x:表示從第x個桶中抽取數據
y:表示每y個桶中抽取一次數據(必須是分桶數量的倍數 or 因子)

   假如已經分了6個桶,則:

    1. bucket 2 out of 3 表示:每3個桶中抽取第2個桶中的數據,總共抽取6/3=2次。即:共需要抽取第2、2+3=5號桶共計2個分桶的數據
    2. bucket 2 out of 6 表示:每6個桶中抽取第2個桶中的數據,總共抽取6/6=1次。即:共需要抽取第2號桶共計1個分桶的數據
    3. bucket 2 out of 12 表示:每12個桶中抽取第2個桶中的數據,總共抽取6/12=0.5次。即:共需要抽取第2號桶中的一半數據

 

【用法簡介】

1.開啟支持分桶

set hive.enforce.bucketing=true;    -- 默認:false --

  設置為 true 之后,mr 運行時會根據 bucket 的個數自動分配 reduce task的個數。

  當然,用戶也可以通過 mapred.reduce.tasks 自己設置 reduce 任務個數,但分桶時不推薦使用。注意:一次作業產生的桶(文件數量)和 reduce task 個數一致)

 

2.往分桶表中加載數據

/* 往分桶表中插入數據的語法類似下面 */
insert into table bucket_table select columns from tbl;    -- 全新插入 --

insert overwrite table bucket_table select columns from tbl;    -- 覆蓋重寫 --

 

3.分桶表數據抽樣

/*
抽樣語法:TABLESAMPLE(BUCKET x OUT OF y)。其中:
x:表示從第x個桶中抽取數據
y:表示每y個桶中抽取一次數據(必須是分桶數量的倍數 or 因子)
*/
select * from bucket_table tablesample(bucket 1 out of 4 on columns);

 

【用法舉例】

1. 假設本地文件 /root/hivedata/ft 中有以下內容:

zhang   12
lisi    34
wange   23
zhouyu  15
guoji   45
xiafen  48
yanggu  78
liuwu   41
zhuto   66
madan   71
sichua  89

 

2. 新建Hive常規表並導入本地文件:

hive> CREATE TABLE ft( id INT, name STRING, age INT)
      > ROW FORMAT DELIMITED FIELDS TERMINATED BY'\t';
OK
Time taken: 0.216 seconds

hive> load data local inpath'/root/hivedata/ft' into table ft;
Loading data to table hehe.ft
Table hehe.ft stats: [numFiles=1, totalSize=127]
OK
Time taken: 1.105 seconds

hive> select *from ft;
OK
1    zhang    12
2    lisi    34
3    wange    23
4    zhouyu    15
5    guoji    45
6    xiafen    48
7    yanggu    78
8    liuwu    41
9    zhuto    66
10    madan    71
11    sichua    89
NULL    NULL    NULL
Time taken: 0.229 seconds, Fetched: 12 row(s)

 

3. 創建分桶表:

hive> create table fentong(
    > id  int,
    > name string,
    > age int,)clustered by(age) into 4 buckets        -- 以字段age來划分成4個桶 --
    > row format delimited fields terminated by ',';

  每行數據具體落入幾號分桶的規則如下:

    1. 用表中指定的字段值(比如age)來除以桶的個數4;
    2. 結果取余數,也就是求模(若余數為0就放到1號桶,余數為1就放到2號桶,余數為2就放到3號桶,余數為3就放到4號桶)

 

4. 給分桶表導入數據:

hive> insert into table fentong select name,age from ft;

 

5. 查詢分桶表數據以確認正確導入:

hive> select * from  fentong

 

6. 我們來看看分桶表的數據如何使用:

hive> select id, name, age from fentong tablesample(bucket 1 out of 4 on age);
OK
NULL    NULL    NULL
6    xiafen    48
1    zhang    12

hive> select id, name, age from fentong tablesample(bucket 2 out of 4 on age);
OK
11    sichua    89
8    liuwu    41
5    guoji            45

hive> select id, name, age from fentong tablesample(bucket 3 out of 4 on age);
OK
9    zhuto    66
7    yanggu    78
2    lisi    34

 

 


免責聲明!

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



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