HIVE分桶原理和样例

Hive中有数据分区的方案,也有数据分桶的方案,今天我们就来探讨下数据分桶 以及数据分桶使用的场景。

该篇文章主要分为一下几个部分:

1.数据分桶的适用场景

2.数据分桶的原理

3.数据分桶的作用

4.如何创建数据分桶表

5.如何将数据插入分桶表

6.针对于分桶表的数据抽样

7.数据分桶的一些缺陷

数据分桶的适用场景:

分区提供了一个隔离数据和优化查询的便利方式,不过并非所有的数据都可形成合理的分区,

尤其是需要确定合适大小的分区划分方式,(不合理的数据分区划分方式可能导致有的分区数据过多,而某些分区没有什么数据的尴尬情况)

试试分桶是将数据集分解为更容易管理的若干部分的另一种技术。

数据分桶的原理:

跟MR中的HashPartitioner的原理一模一样

    MR中:按照key的hash值去模除以reductTask的个数

    Hive中:按照分桶字段的hash值去模除以分桶的个数

Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

数据分桶的作用:

好处:
1、方便抽样

2、提高join查询效率

(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

(2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

创建数据分桶表:

创建数据分桶表与普通表的表区别并不太大,如下为一个创建数据分桶表的示例:

use clickcube;

CREATE EXTERNAL TABLE clickcube_mid(
logtype bigint,
date string,
hour bigint,
projectid bigint,
campaignid bigint,
templateid bigint,
mediaid bigint,
slotid bigint,
channeltype bigint,
regioncode string,
campclick bigint,
campimp bigint,
mediaclick bigint,
mediaimp bigint,
templateimp bigint,
templatecampimp bigint,
mediaclickcost double,
campclickcost double)
PARTITIONED BY (
day string)
CLUSTERED BY (
campaignid, mediaid ) INTO 100 BUCKETS
ROW FORMAT SERDE
‘org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe’
STORED AS INPUTFORMAT
‘org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat’
OUTPUTFORMAT
‘org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat’
TBLPROPERTIES (
‘last_modified_by’=‘cloudera-scm’,
‘last_modified_time’=‘1530676367’,
‘transient_lastDdlTime’=‘1530676367’)

其实主要注意的地方就如下的点:

CLUSTERED BY (

campaignid, mediaid ) INTO 100 BUCKETS

如何将数据插入分桶表

将数据导入分桶表主要通过以下步骤

第一步:

从hdfs或本地磁盘中load数据,导入中间表

第二步:

通过从中间表查询的方式的完成数据导入



  分桶的实质就是对 分桶的字段做了hash 然后存放到对应文件中,所以说如果原有数据没有按key hash ,

需要在插入分桶的时候hash, 也就是说向分桶表中插入数据的时候必然要执行一次MAPREDUCE,

这也就是分桶表的数据基本只能通过从结果集查询插入的方式进行导入

这里我们主要讲解第二步:

主要的过程我们写为一个SQL

use clickcube;

set hive.enforce.bucketing = true;

INSERT OVERWRITE TABLE clickcube_mid_bucket
PARTITION( day = ‘2018-07-03’ )
SELECT
clickcube_mid.logtype,
clickcube_mid.date,
clickcube_mid.hour,
clickcube_mid.projectid,
clickcube_mid.campaignid,
clickcube_mid.templateid,
clickcube_mid.mediaid,
clickcube_mid.slotid,
clickcube_mid.channeltype,
clickcube_mid.regioncode,
clickcube_mid.campclick,
clickcube_mid.campimp,
clickcube_mid.mediaclick,
clickcube_mid.mediaimp,
clickcube_mid.templateimp,
clickcube_mid.templatecampimp,
clickcube_mid.mediaclickcost,
clickcube_mid.campclickcost
FROM clickcube_mid
WHERE day = ‘2018-07-03’

这里我们需要注意几点

我们需要确保reduce 的数量与表中的bucket 数量一致,为此有两种做法

1.让hive强制分桶,自动按照分桶表的bucket 进行分桶。(推荐)

set hive.enforce.bucketing = true;

2.手动指定reduce数量

set mapreduce.job.reduces = num;

/

set mapreduce.reduce.tasks = num;

并在 SELECT 后增加CLUSTER BY 语句

下面展示下整体的数据导入脚本

主要分为3个文件:

-rw-r–r--. 1 root root 637 7月 4 20:37 insert_into_bucket.hql
-rw-r–r--. 1 root root 37 7月 4 20:26 insert_into_bucket.init
-rwxr-xr-x. 1 root root 1788 7月 4 20:27 insert_into_bucket.sh

insert_into_bucket.hql 数据导入HQL

insert_into_bucket.init 设置初始环境

insert_into_bucket.sh 主体执行脚本

insert_into_bucket.sh

#! /bin/bash

set -o errexit

source /etc/profile
source ~/.bashrc

ROOT_PATH=$(dirname $(readlink -f $0))
echo $ROOT_PATH

date_pattern_old=’1{4}-[0-9]{1,2}-[0-9]{1,2} ′ d a t e p a t t e r n = ′ [ 0 − 9 ] 4 − ( ( 0 ( [ 1 − 9 ] 1 ) ) ∣ ( 1 [ 1 ∣ 2 ] ) ) − ( ( [ 0 − 2 ] ( [ 0 − 9 ] 1 ) ) ∣ ( 3 [ 0 ∣ 1 ] ) ) ' date_pattern='^[0-9]{4}-((0([1-9]{1}))|(1[1|2]))-(([0-2]([0-9]{1}))|(3[0|1])) datepattern=[09]4((0([19]1))(1[12]))(([02]([09]1))(3[01]))

#参数数量
argsnum=$#

#一些默认值
curDate=date +%Y%m%d
partitionDate=date -d '-1 day' +%Y-%m-%d
fileLocDate=date -d '-1 day' +%Y-%m-%d

#日志存放位置
logdir=insert_bucket_logs

function tips() {
echo “Usage : insert_into_bucket.sh [date]”
echo “Args :”
echo “date”
echo " date use this format yyyy-MM-dd , ex : 2018-06-02"
echo “============================================================”
echo “Example :”
echo " example1 : sh insert_into_bucket.sh"
echo " example2 : sh insert_into_bucket.sh 2018-06-02"
}

if [ $argsnum -eq 0 ] ; then
echo “No argument, use default value”
elif [ $argsnum -eq 1 ] ; then
echo “One argument, check date pattern”
arg1= 1 i f ! [ [ " 1 if ! [[ " 1if![["arg1" =~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值