Hive的分桶表和抽樣查詢(附帶案例,分桶和分表的區別)
目錄
總結:
①分桶為抽樣查詢而生,分桶表的建立使用【clustered by (分桶欄位)into 桶的個數 buckets】 ,往分桶表中匯入資料的時候,需要藉助第三張表select table_tmp 目的是藉助MapReduce來實現匯入不同的桶中,分桶的規則是分桶欄位的hash值,模Reducer的個數;②分桶切割的是檔案,分割槽並沒有;③抽樣查詢的語法:tablesample(bucket x out of y on 分桶的欄位)
分桶表:
分割槽提供一個隔離資料和優化查詢的便利方式。不過,並非所有的資料集都可形成合理的分割槽。對於一張表或者分割槽,Hive 可以進一步組織成桶,也就是更為細粒度的資料範圍劃分。分桶是將資料集分解成更容易管理的若干部分的另一個技術。分割槽是便於抽樣查詢
1,建立分割槽表: create table stu_bucket(id int,name string) clustered by (id) into 4 buckets row format delimited fields terminated by '\t'; 0: jdbc:hive2://hadoop108:10000> show tables; +-------------+--+ | tab_name | +-------------+--+ | stu1 | | stu2 | | stu_bucket | | stu_ex1 | | stu_ex2 | | stu_par1 | | stu_par2 | +-------------+--+ 使用:desc formatted stu_bucket;檢視該表是否是真的分桶表 在linux下寫入資料: [
[email protected] datas]$ cat student.txt 1001 ss1 1002 ss2 1003 ss3 1004 ss4 1005 ss5 1006 ss6 1007 ss7 1008 ss8 1009 ss9 1010 ss10 1011 ss11 1012 ss12 1013 ss13 1014 ss14 1015 ss15 1016 ss16 [[email protected] datas]$ pwd /opt/module/datas 如果使用:load data local inpath '/opt/module/datas/student.txt' into table stu_bucket; 這種匯入資料的方式,直接將資料丟到stu_bucket所在的檔案下面,並不會將資料拆分成檔案,該種方式形成 的檔案的路徑是:/user/hive/warehouse/db_hive.db/stu_bucket/student.txt 如何清除表中的資料而不影響到表的結構: truncate table stu_bucket; 如何在插入資料的時候完成對資料的切分呢?這應該要使用到MapReduce過程進行計算 先建立一個普通表,然後在使用select該表的內容insert到stu_bucket表中: create table stu_tmp(id int,name string) row format delimited fields terminated by '\t'; load data local inpath '/opt/module/datas/student.txt' into table stu_tmp; 在分桶之前,我們需要將分桶的模式開啟: set hive.enforce.bucketing=true; 0: jdbc:hive2://hadoop108:10000> set hive.enforce.bucketing; +------------------------------+--+ | set | +------------------------------+--+ | hive.enforce.bucketing=true | +------------------------------+--+ insert into table stu_bucket select * from stu_tmp; 通過insert要走MapReduce,我們使用這樣的方式來實現將檔案的切分,檢視一下我們的檔案是否真的分桶了: > !sh hadoop fs -ls /user/hive/warehouse/db_hive.db/stu_bucket Found 4 items -rwxr-xr-x 3 isea supergroup 38 2018-12-02 05:09 /user/hive/warehouse/db_hive.db/stu_bucket/000000_0 -rwxr-xr-x 3 isea supergroup 37 2018-12-02 05:09 /user/hive/warehouse/db_hive.db/stu_bucket/000001_0 -rwxr-xr-x 3 isea supergroup 38 2018-12-02 05:09 /user/hive/warehouse/db_hive.db/stu_bucket/000002_0 -rwxr-xr-x 3 isea supergroup 38 2018-12-02 05:09 /user/hive/warehouse/db_hive.db/stu_bucket/000003_0 我們可以檢視一下檔案的分割的規則: !sh hadoop fs -cat /user/hive/warehouse/db_hive.db/stu_bucket/000000_0 1016 ss16 1012 ss12 1008 ss8 1004 ss4 !sh hadoop fs -cat /user/hive/warehouse/db_hive.db/stu_bucket/000001_0 1009 ss9 1005 ss5 1001 ss1 1013 ss13 !sh hadoop fs -cat /user/hive/warehouse/db_hive.db/stu_bucket/000002_0 1010 ss10 1002 ss2 1006 ss6 1014 ss14 !sh hadoop fs -cat /user/hive/warehouse/db_hive.db/stu_bucket/000003_0 1003 ss3 1011 ss11 1007 ss7 1015 ss15 我們觀察得知分桶的規則是計算分桶欄位的hash值,模上桶的個數得到桶號。如此一來,就能幾乎做到均分, 便於我們對資料的抽樣。
分桶和分割槽的區別:
分割槽針對的是資料的儲存路徑;分桶針對的是資料檔案。
①分割槽之後形成的檔案是類似於:/user/hive/warehouse/db_hive.db/stu_bucket/student.txt;
②分桶之後形成的檔案類似於:student.txt將被分成了四個檔案,如果桶對個數是4的話:
/user/hive/warehouse/db_hive.db/stu_bucket/000000_0
/user/hive/warehouse/db_hive.db/stu_bucket/000001_0
/user/hive/warehouse/db_hive.db/stu_bucket/000002_0
/user/hive/warehouse/db_hive.db/stu_bucket/000003_0
抽樣查詢:
對於非常大的資料集,有時使用者需要使用的是一個具有代表性的查詢結果而不是全部結果。Hive可以通過對錶進行抽樣來滿足這個需求抽樣查詢的語法:
TABLESAMPLE(BUCKET x OUT OF y) 。注意:x的值必須小於等於y的值
y必須是table總bucket數的倍數或者因子。hive根據y的大小,決定抽樣的比例。例如,table總共分了4份,當y=2時,抽取(4/2=)2個bucket的資料,當y=8時,抽取(4/8=)1/2個bucket的資料。x表示從哪個bucket開始抽取,如果需要取多個分割槽,以後的分割槽號為當前分割槽號加上y。例如,table總bucket數為4,tablesample(bucket 1 out of 2),表示總共抽取(4/2=)2個bucket的資料,抽取第1(x)個和第3(x+y)個bucket的資料。
下面是具體的案例:
首先,我們檢視一下該stu_bucket中的所有資料:
> select * from stu_bucket;
+----------------+------------------+--+
| stu_bucket.id | stu_bucket.name |
+----------------+------------------+--+
| 1016 | ss16 |
| 1012 | ss12 |
| 1008 | ss8 |
| 1004 | ss4 |
| 1009 | ss9 |
| 1005 | ss5 |
| 1001 | ss1 |
| 1013 | ss13 |
| 1010 | ss10 |
| 1002 | ss2 |
| 1006 | ss6 |
| 1014 | ss14 |
| 1003 | ss3 |
| 1011 | ss11 |
| 1007 | ss7 |
| 1015 | ss15 |
+----------------+------------------+--+
> select * from stu_bucket tablesample(bucket 1 out of 4 on id);
+----------------+------------------+--+
| stu_bucket.id | stu_bucket.name |
+----------------+------------------+--+
| 1016 | ss16 |
| 1012 | ss12 |
| 1008 | ss8 |
| 1004 | ss4 |
+----------------+------------------+--+
> select * from stu_bucket tablesample(bucket 1 out of 2 on id);
+----------------+------------------+--+
| stu_bucket.id | stu_bucket.name |
+----------------+------------------+--+
| 1016 | ss16 |
| 1012 | ss12 |
| 1008 | ss8 |
| 1004 | ss4 |
| 1010 | ss10 |
| 1002 | ss2 |
| 1006 | ss6 |
| 1014 | ss14 |
+----------------+------------------+--+
> select * from stu_bucket tablesample(bucket 1 out of 8 on id);
+----------------+------------------+--+
| stu_bucket.id | stu_bucket.name |
+----------------+------------------+--+
| 1016 | ss16 |
| 1008 | ss8 |
+----------------+------------------+--+
總結:
①分桶表的建立使用clustered by (分桶欄位)into 桶的個數 buckets ,往分桶表中匯入資料的時候,需要藉助第三張表select table_tmp 目的是藉助MapReduce來實現匯入不同的桶中,分桶的規則是分桶欄位的hash值,模Reducer的個數;②分桶切割的是檔案,分割槽並沒有;③抽樣查詢的語法:tablesample(bucket x out of y on 分桶的欄位)