Hive分桶之BUCKET详解

Bucket


  1. 对于每一个表(table)或者分区(partition), Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

  2. 把表(或者分区)组织成桶(Bucket)有两个理由:
    (1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
    (2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

    下面来一个例子:

Create table dz_test(
    id  bigint  comment’编号’,(ps:comment为注释)
    name string comment’姓名’
)comment’编号与姓名表’
Partitioned by(pdate string)
Clustered by(id)     按id分桶,自动哈希分桶
Sorted by(id)   按id排序
Into 4 buckets   分成4个桶
Row format delimited 设置创建的表在加载数据的时候,支持的列分隔符
Fields terminated by ‘\t’  每个字段按\t分割
Lines terminated by’\n’ stored as textfile; 按\n为断行符,指定导入的文件为纯文本。
Hive本身支持的文件格式只有:Text File,Sequence File,如果数据需要压缩,使用 [STORED AS SEQUENCE]

够详细了吧,下面load数据:

    插入数据之前需要设置参数hive.enforce.bucketing=true,以强制hive的reducer数目为分桶数。如果不设置这个hive参数,最后的桶个数可能不是建表语句中的个数。另外,也可以通过将参数mapred.reduce.tasks设置为桶的数目来控制reducer的数目,建议采用第一种方式。
Set hive.enforce.bucketing=true;
Load data local inpath’/home/Hadoop/….’ overwrite into table dz_test partition(pdate=‘2015-10’)
物理上,每个桶就是表(或分区)目录里的一个文件。它的文件名并不重要,但是桶 n 是按照字典序排列的第 n 个文件。事实上,桶对应于 MapReduce 的输出文件分区:一个作业产生的桶(输出文件)和reduce任务个数相同。

我们可以通过查看刚才 创建的bucketd_users表的布局来了解这一情况。运行如下命令:  
查看表的结构:
hive> dfs -ls /user/hive/warehouse/dz_test; 
将显示有4个新建的文件。文件名如下(文件名包含时间戳,由Hive产生,因此 每次运行都会改变): 
attempt_201701221636_0016_r_000000_0 
attempt_201701221636_0016_r-000001_0 
attempt_201701221636_0016_r_000002_0 
attempt_201701221636_0016_r_000003_0 
第一个桶里包括用户ID和4,因为一个INT的哈希值就是这个整数本身,在这里 除以桶数(4)以后的余数:2
读取数据,看每一个文件的数据:
hive> dfs -cat /user/hive/warehouse/dz_test/*0_0; 
0 Nat 
4 Ann 
用TABLESAMPLE子句对表进行取样,我们可以获得相同的结果。这个子句会将 查询限定在表的一部分桶内,而不是使用整个表:
. 对桶中的数据进行采样:
hive> SELECT * FROM dz_test 
>TABLESAMPLE(BUCKET 1 OUT OF 4 ON id); 
0 Nat 
4 Ann 
桶的个数从1开始计数。因此,前面的查询从4个桶的第一个中获取所有的用户。 对于一个大规模的、均匀分布的数据集,这会返回表中约四分之一的数据行。我们 也可以用其他比例对若干个桶进行取样(因为取样并不是一个精确的操作,因此这个 比例不一定要是桶数的整数倍)。例如,下面的查询返回一半的桶:
7. 查询一半返回的桶数:
hive> SELECT * FROM dz_test 
>    TABLESAMPLE(BUCKET 1 OUT OF 2 ON id); 
0 Nat 
4 Ann 
2 Joe 
因为查询只需要读取和TABLESAMPLE子句匹配的桶,所以取样分桶表是非常高效 的操作。如果使用rand()函数对没有划分成桶的表进行取样,即使只需要读取很 小一部分样本,也要扫描整个输入数据集: 
hive〉 SELECT * FROM dz_test 
> TABLESAMPLE(BUCKET 1 OUT OF 4 ON rand()); 
2 Doe 
①从Hive 0.6.0开始,对以前的版本,必须把mapred.reduce .tasks设为表中要填 充的桶的个数。如果桶是排序的,还需要把hive.enforce.sorting设为true。 
②显式原始文件时,因为分隔字符是一个不能打印的控制字符,因此字段都挤在一起。 
  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值