Hive 之 查詢 04-分桶及抽樣查詢

Hive 之 查詢 04-分桶及抽樣查詢

一、 分桶表數據存儲

分區針對的是數據的存儲路徑, 分桶針對的是數據文件;

分區提供一個隔離數據和優化查詢的便利方式。 不過, 並非所有的數據集都可以形成合理的分區。 特別是要確定合適的劃分大小這個問題。

【注】分桶類似於 Hadoop 裏面的分區;

如:

創建分桶表:

hive (default)> create table stu_buck(
              > id int, 
              > name string)
              > clustered by(id)
              > into 4 buckets
              > row format delimited fields terminated by '\t';
OK
Time taken: 2.17 seconds

查看錶結構:

hive (default)> desc formatted stu_buck;
OK	 
... ...                	 
Num Buckets:        	4                   	 
Bucket Columns:     	[id]
... ...              
Time taken: 0.449 seconds, Fetched: 28 row(s)

導入數據:

hive (default)> load data local inpath
              > '/opt/module/data/student.txt'
              > into table stu_buck;
Loading data to table default.stu_buck
Table default.stu_buck stats: [numFiles=1, totalSize=151]
OK
Time taken: 0.767 seconds

查看數據:

hive (default)> select * from stu_buck;
OK
stu_buck.id	stu_buck.name
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
Time taken: 0.324 seconds, Fetched: 16 row(s)

由於 load 命令加載數據, 實際上使用的是 hadoop 的 put 命令, 所以數據並沒有被分到四個桶裏面, 而是一個文件。 可以查看 hadoop 的 /user/hive/warehouse/stu_buck/路徑下只有一個 student.txt文件。

所以這種方式不行。

另一種方式: 創建一個普通表(不分區、 不分桶):

hive (default)> create table stu(
              > id int,
              > name string
              > )
              > row format delimited fields terminated by '\t';
OK
Time taken: 0.038 seconds

然後加載數據到 stu表中:

hive (default)> load data local inpath 
              > '/opt/module/data/student.txt'
              > into table stu;
Loading data to table default.stu
Table default.stu stats: [numFiles=4, numRows=0, totalSize=232, rawDataSize=0]
OK
Time taken: 0.26 seconds

然後使用下面這種方式將 stu中的數據導入到 stu_buck中(爲了讓它走 MR, 這樣 stu_buck才能讀到 id 這個分桶字段):

hive (default)> insert into table stu_buck
              > select * from stu;

... ...
OK
stu.id	stu.name
Time taken: 29.734 seconds

結果發現 stu_buck的表裏面依舊是一個文件, 並沒有分桶。

我們需要設置些屬性然後再導入數據:

hive (default)> set hive.enforce.bucketing=true;
hive (default)> set set mapreduce.job.reducers=-1;

分別設置了強制分桶, 並將 Reducer 的個數設置爲 -1(不限制);

然後再導入數據:

hive (default)> insert into table stu_buck
              > select * from stu;

再次查看 Hadoop 上/user/hive/warehouse/stu_buck/路徑下有四個文件:

[root@hadoop102 data]# hadoop fs -ls /user/hive/warehouse/stu_buck/
Found 4 items
-rwxr-xr-x   3 root supergroup         38 2020-04-02 00:49 /user/hive/warehouse/stu_buck/000000_0
-rwxr-xr-x   3 root supergroup         37 2020-04-02 00:49 /user/hive/warehouse/stu_buck/000001_1
-rwxr-xr-x   3 root supergroup         38 2020-04-02 00:48 /user/hive/warehouse/stu_buck/000002_0
-rwxr-xr-x   3 root supergroup         38 2020-04-02 00:49 /user/hive/warehouse/stu_buck/000003_0

查詢數據表中的數據:

hive (default)> select * from stu_buck;
OK
stu_buck.id	stu_buck.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
Time taken: 0.032 seconds, Fetched: 16 row(s)

二、 分桶抽樣查詢

對於非常大的數據集,有時用戶需要使用的是一個具有代表性的查詢結果而不是全部結果。 Hive 可以通過對錶進行抽樣來滿足這個需求。

查詢表 stu_buck中的數據

hive (default)> select * from stu_buck
              > tablesample(bucket 1 out of 4 on id);
OK
stu_buck.id	stu_buck.name
1016	ss16
1012	ss12
1008	ss8
1004	ss4
Time taken: 1.977 seconds, Fetched: 4 row(s)

注:tablesample是抽樣語句,語法: TABLESAMPLE(BUCKET x OUT OF 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 的數據。

【注意】x 的值必須小於等於 y 的值,否則:

hive (default)> select * from stu_buck
              > tablesample(bucket 5 out of 4 on id);
FAILED: SemanticException [Error 10061]: Numerator should not be bigger than denominator in sample clause
 for table stu_buck
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章