Hive分桶(bucket)

一 什么是桶的概念,和分区有啥区别?

对于每一个表或者分区,可以进一步细分成桶,桶是对数据进行更细粒度的划分。默认时对某一列进行hash,使用hashcode对 桶的个数求模取余,确定哪一条记录进入哪一个桶。

Hive在查询数据的时候,一般会扫描整个表的数据,会消耗很多不必要的时间。有些时候,我们只需要关心一部分数据,比如WHERE子句所接的查询条件,那这时候这种全表扫描的方式是很影响性能的。从而引入了分区的概念。分区就是对某列有相同的数据或者某一个数据范围的数据进行分类,这样在查询的时候,就可以只是针对分区查询,从而不必全表扫描。

 

二 如何分桶? 如何导入数据?

2.1导入数据

CREATE TABLE IF NOT EXISTS t_movie(

idINT,

nameSTRING,

directorSTRING,

countrySTRING,

yearSTRING,

monthSTRING

)ROWFORMAT DELIMITED FIELDS TERMINATED BY ',';

COMMENT'Create Bucket Movie Table'

PARTITIONEDBY (area STRING)

CLUSTEREDBY (country) INTO 4 BUCKETS

ROWFORMAT DELIMITED FIELDS TERMINATED BY ','

STOREDAS ORC;

CLUSTEREDBY: 指定根据哪一列来划分桶

INTOnum BUCKTES: 指定划分几个桶

2.2导入数据

我们需要设置sethive.enforce.bucketing=true;

如果我们没有设置hive.enfoce.bucketing这个参数,那么我们需要设置和分桶个数相匹配的Reducer数目,set mapred.reduce.tasks=4,并且查询的时候需要添加CLSUTERBY子句。

所以如果设置了我们查询的时候就不必设置Reducer数目,和查询的时候不必指定CLSUTRER BY子句。

INSERT INTO TABLE bucket_movie PARTITION(area='China') SELECT * FROM t_movie WHERE country = 'China';

INSERT INTO TABLE bucket_movie PARTITION(area='America') SELECT * FROM t_movie WHERE country = 'America';

INSERT INTO TABLE bucket_movie PARTITION(area='Japan') SELECT * FROM t_movie WHERE country = 'Japan';

 

三 分桶作用

3.1 获得更高的查询效率

我们试想一个场景:比如2张大表需要JOIN,JOIN的字段比如是id,我们进行Reduce Side Join(ShuffleJoin)合适吗?肯定不合适。

如果我们用Map Side Join呢?Map Side Join场景是小表Join大表比较适合,因为会把小表数据是通过DistributedCache 分发到各个Map

Side,然后加载到内存和每一个Map 任务处理的大表进行JOIN,这样就不必要去做Reduce JOIN, 但是如果是大表就不太适合放到内存去了。

所以Bucket这时候在Map SideJoin就有勇武之地了。

原理:

2张表对于连接的字段进行分桶,处理左边表内某个桶的Mapper他知道右边表内对应的行在对应的桶内,因此Mapper只需要获取那个桶,然后取得数据进行JOIN

 

如图示:

我们需要将用户表和订单表进行join。


如果我们没有分桶,那么这2张大表在JOIN的时候,效率是很低的。

那现在我们引入桶的概念,那么用户表按照id分桶,订单表按照

cid分桶,那么相同id都会归入一个桶。那么此时再进行JOIN的时候是按照桶来JOIN的,那么大大减少了JOIN的数量。

 

但是这是需要一定条件的,否则JOIN出来的结果是不正确的:

用户表的桶的个数必须是订单表的倍数或者因子,也就是说订单表100各个桶,那么用户表可以是200,300或者10,20,25,50

为什么要这么做呢?

我们知道分桶会对该列进行hash,然后根据桶的数量取余计算每一个记录落在哪一个桶。

比如A表4个桶,B表5个桶,那么假设hash取余之后的数A表肯定是0,1,2,3 那么B表的话则是0,1,2,3,4

问题来呢?如果假设hashcode得到的值为8,那么在A表,这条数据就落在0这个桶内,而在表则会落在3这个桶内.

 

如果要想Hive执行BucketMap Join,我们需要确保这个参数是否为true:

hive.optimize.bucketmapjoin= true

step1: 先将小表做map,数据放入hashtable,广播到所有大表的Map端,大表map端接受了小表的hashtable,并不需要合并成一个大的hashtable,直接可以进行map操作,map操作会产生桶个数的Split,然后小表数据放入内存,然后大表对应的split拿出来判断。但是这时候还是有可能内存不够用,所以并没有完全解决Map Side Join在小表完全装在进内存的限制。

 

如果桶中的数据可以根据一个或多个列另外进行排序。由于这样对每个桶的连接变成了高效的归并排序(merge-sort), 因此可以进一步提升map端连接的效率。以下语法声明一个表使其使用排序桶: 

CREATE TABLE table_name (col_name data_type,……)

CLUSTERED BY (col_name) SORTED BY(col_name ASC|DESC)

 

set hive.optimize.bucketmapjoin.sortedmerge = true;

sethive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHive

InputFormat;

 

3.2 方便我们抽样

我们知道抽象:

SELECT * FROM table_name TABLESAMPLE(nPERCENT);

就是针对n%进行取样

有了桶之后呢?

SELECT * FROM film TABLESAMPLE(BUCKET x OUTOF y)

x:表示从哪一个桶开始抽样

y:抽样因素,必须是桶数的因子或者倍数,假设桶数是100那么y可以是200,10,20,25,5。假设桶数是100,y=25时抽取(100/25) = 4个bucket数据;当y=200的时候(100/200) = 0.5个bucket的数据


  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫言静好、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值