Hive查詢(四)分桶及抽樣查詢
一、分桶表數據存儲
分區針對的是數據的存儲路徑;分桶針對的是數據文件。
分區提供一個隔離數據和優化查詢的便利方式。不過,並非所有的數據集都可形成合理的分區,特別是之前所提到過的要確定合適的划分大小這個疑慮。
分桶是將數據集分解成更容易管理的若干部分的另一個技術。
1.先創建分桶表,通過直接導入數據文件的方式
1)數據准備
2)創建分桶表
create table stu_buck1(id int, name string) clustered by(id) into 4 buckets row format delimited fields terminated by '\t'; |
3)查看表結構
hive (default)> desc formatted stu_buck;
Num Buckets: 4
4)導入數據到分桶表中
hive (default)> load data local inpath '/opt/module/hiveTest/s/student.txt' into table stu_buck1;
5)查看創建的分桶表中是否分成4個桶
發現並沒有分成4個桶。是什么原因呢?(load加載方式不會分桶)
2.創建分桶表時,數據通過子查詢的方式導入
1)先建一個普通的stu表
create table stu(id int, name string) row format delimited fields terminated by '\t'; |
2)向普通的stu表中導入數據
load data local inpath '/opt/module/hiveTest/s/student.txt' into table stu; |
3)清空stu_buck表中數據
truncate table stu_buck1; select * from stu_buck1; |
4)導入數據到分桶表,通過子查詢的方式
insert into table stu_buck1 select id, name from stu; |
5)發現還是只有一個分桶
6)需要設置一個屬性
hive (default)> set hive.enforce.bucketing;
hive.enforce.bucketing=false
將分桶屬性設置為true
hive (default)> set hive.enforce.bucketing=true; hive (default)> set mapreduce.job.reduces=-1; hive (default)> truncate table stu_buck1; hive (default)> insert into table stu_buck1 select id, name from stu; |
7)查詢分桶的數據
hive (default)> select * from stu_buck1; OK stu_buck1.id stu_buck1.name 1040 黃忠 1036 董卓 1032 妲己 1028 墨菲特 1024 干將 1020 孫斌 1016 嬴政 1012 劉備 1008 諸葛亮 1004 趙六 1005 李琪 1029 易 1037 馬謖 1017 韓信 1001 張三 1033 呂布 1009 司馬懿 1013 曹操 1025 白起 1021 大橋 1010 張飛 1038 夏侯? 1022 小喬 1034 張苞 1002 李四 1026 李白 1018 孫權 1030 亞瑟 1014 曹植 1006 趙雲 1015 曹丕 1007 黃月英 1027 李信 1023 魯班 1019 孫尚香 1003 王五 1011 關羽 1039 夏侯淵 1035 魯肅 1031 安其拉 |
二、分桶抽樣查詢
對於非常大的數據集,有時用戶需要使用的是一個具有代表性的查詢結果而不是全部結果。Hive可以通過對表進行抽樣來滿足這個需求。
查詢表stu_buck1中的數據。
hive (default)> select * from stu_buck1 tablesample(bucket 1 out of 4 on id); OK stu_buck1.id stu_buck1.name 1040 黃忠 1036 董卓 1032 妲己 1028 墨菲特 1024 干將 1020 孫斌 1016 嬴政 1012 劉備 1008 諸葛亮 1004 趙六 Time taken: 2.768 seconds, Fetched: 10 row(s) |
注:tablesample是抽樣語句,語法:TABLESAMPLE(BUCKET x OUT OF y) 。
hive (default)> select * from stu_buck1 tablesample(bucket 1 out of 3 on id); |
不是桶數的倍數或者因子也可以,但是不推薦。
y必須是table總bucket數的倍數或者因子。hive根據y的大小,決定抽樣的比例。
例如,table總共分了4份(4個bucket),當y=2時,抽取(4/2=)2個bucket的數據,當y=8時,抽取(4/8=)1/2個bucket的數據。
hive (default)> select * from stu_buck tablesample(bucket 1 out of 2 on id); |
x表示從哪個bucket開始抽取。
例如,table總bucket數為4,tablesample(bucket 4 out of 4),表示總共抽取(4/4=)1個bucket的數據,抽取第4個bucket的數據。
hive (default)> select * from stu_buck tablesample(bucket 1 out of 8 on id); OK stu_buck1.id stu_buck1.name 1040 黃忠 1032 妲己 1024 干將 1016 嬴政 1008 諸葛亮 Time taken: 0.388 seconds, Fetched: 5 row(s) |
注意:x的值必須小於等於y的值,否則
FAILED: SemanticException [Error 10061]: Numerator should not be bigger than denominator in sample clause for table stu_buck
三、數據塊抽樣
Hive提供了另外一種按照百分比進行抽樣的方式,這種是基於行數的,按照輸入路徑下的數據塊百分比進行的抽樣。
hive (default)> select * from stu tablesample(0.1 percent) ; |
提示:這種抽樣方式不一定適用於所有的文件格式。另外,這種抽樣的最小抽樣單元是一個HDFS數據塊。因此,如果表的數據大小小於普通的塊大小128M的話,那么將會返回所有行。