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的话,那么将会返回所有行。