首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浪尖,请问如何确定hive分桶数?

浪尖,请问如何确定hive分桶数?

作者头像
Spark学习技巧
发布2018-08-01 12:02:13
4.2K0
发布2018-08-01 12:02:13
举报
文章被收录于专栏:Spark学习技巧Spark学习技巧

今日,有人在星球问了一个比较好的问题:浪尖,请问如何确定hive的分桶数呢?

关于这个问题,浪尖想写个文章,谈谈我自己的看法,当然也欢迎有经验的同学么留言。

顺便打个广告,更多优质文章和问题答疑及视频教程请点击原文链接,加入浪尖知识星球-Spark技术学院获取。

需要了解hive的分区分桶及二者的区别

hive的分区和分桶

相关hive文章

Hive性能优化(全面)

为啥要分桶?

首先要知道,Hive 分区提供了一种将hive表数据分成多个文件/目录的方法。 但是,它只在少数情况下提供有效的效果,比如:

- 当分区数量有限时。

-且 分区的大小相对相等。

然而,这基本是不可能。 例如,根据国家/地区等地理位置对表格进行分区。 那么会发现一些较大国家产生的分区会很大(例如:4-5个国家本身占总数据的70-80%)。 小国家会产生小分区(世界上所有国家仍然可能只占总数据的20-30%)。 因此,这时分区将不是理想的。为了解决过度分区的问题,Hive提供了分桶的概念。 这是将表数据集分解为更易于管理的部分的另一种有效技术。

hive分桶的特点

分桶的基本原理是分桶列的hash_function%mod = bucketId。

可以看到前提是,我们要指定mod,也即是分桶的个数,其实该值也是运行的最大reduce个数。

分桶的特征如下:

  1. hash_function取决于bucketing列的类型。
  2. 具有相同分段列的记录将始终存储在同一个桶中。
  3. 使用CLUSTERED BY将表分成桶。
  4. 通常,在表目录中,每个存储桶只是一个文件,并且存储桶编号是从1开始的。
  5. 可以先分区再分桶,也可以直接分桶。
  6. 此外,Bucketed表将创建几乎相等的分布式数据文件块(取决于分桶列是否离散)。

hive分桶的优势

  1. 与非分桶表相比,分桶表提供了高效采样。通过采样,我们可以尝试对一小部分数据进行查询,以便在原始数据集非常庞大时进行测试和调试。
  2. 由于数据文件是相同大小的部分,map-side join在分桶表上执行的速度比分区表块很多。在map-side join时,处理左侧表的map知道要匹配的右表中的行在相关的桶中,因此只需要检索该桶。
  3. 分桶表查询速度快于非分桶表。
  4. Bucketing概念还提供了灵活性,可以使每个存储桶中的记录按一列或多列进行排序。 这使得map-side join更加高效,因为每个存储桶的join变为高效的合并排序(merge-sort)。

hive分桶的缺点

指定bucketing并不能确保正确填充表。 数据加载到存储桶需要由我们自己处理。

举个例子

创建分区分桶表

比如创建一个表,按照国家分区,州分桶,然后对城市进行升序排序

CREATE TABLE bucketed_user(
          firstname VARCHAR(64),
          lastname  VARCHAR(64),
          address   STRING,
          city     VARCHAR(64),
        state     VARCHAR(64),
          post      STRING,
          phone1    VARCHAR(64),
          phone2    STRING,
          email     STRING,
          web       STRING
          )
        COMMENT 'A bucketed sorted user table'
          PARTITIONED BY (country VARCHAR(64))
        CLUSTERED BY (state) SORTED BY (city) INTO 32 BUCKETS
          STORED AS SEQUENCEFILE;

插入数据

与分区表类似,我们不能直接使用LOAD DATA(LOCAL)INPATH命令加载数据到分桶表,而是需要使用INSERT OVERWRITE TABLE ... SELECT ... FROM子句来填充分桶表。 为此,我们将在hive中创建一个临时表,其中包含该表中输入文件中的所有列,我们将复制到目标bucketed表中。

假设我们已经创建了temp_user临时表,下面是用于使用temp_user表填充分桶表的HiveQL。

要填充分桶表,我们需要设置属性hive.enforce.bucketing = true,以便Hive知道创建表定义中声明的桶数。

set hive.enforce.bucketing = true;
 
INSERT OVERWRITE TABLE bucketed_user PARTITION (country)
        SELECT  firstname ,
            lastname  ,
            address   ,
          city      ,
        state     ,
            post      ,
            phone1    ,
            phone2    ,
            email     ,
            web       ,
            country   
          FROM temp_user;

注意:

属性hive.enforce.bucketing = true类似于分区中的hive.exec.dynamic.partition = true属性。 通过设置此属性,我们将在将数据加载到hive表时启用动态分桶。

它会自动将reduce任务的数量设置为等于表定义中提到的桶数(例如,在我们的例子中为32),并自动从表定义中选择clustered by列。

如果我们不在Hive Session中设置此属性,我们必须手动将相同的信息在上面的INSERT ... SELECT语句结尾处传递给Hive,也即要运行的reduce任务的数量(例如在我们的例子中,通过set mapred.reduce.tasks = 32)和CLUSTER BY (state)还有SORT BY(city)子句。

完整的sql语句如下

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=1000;
set hive.enforce.bucketing = true;
 
DROP TABLE IF EXISTS bucketed_user;
 
CREATE TEMPORARY TABLE temp_user(
         firstname VARCHAR(64),
         lastname  VARCHAR(64),
         address   STRING,
         country   VARCHAR(64),
         city      VARCHAR(64),
         state     VARCHAR(64),
         post      STRING,
         phone1    VARCHAR(64),
         phone2    STRING,
         email     STRING,
         web       STRING
         )
         ROW FORMAT DELIMITED 
           FIELDS TERMINATED BY ','
           LINES TERMINATED BY '\n'
       STORED AS TEXTFILE;
 
LOAD DATA LOCAL INPATH '/home/user/user_table.txt' INTO TABLE temp_user;
 
CREATE TABLE bucketed_user(
         firstname VARCHAR(64),
         lastname  VARCHAR(64),
         address   STRING,
         city        VARCHAR(64),
       state     VARCHAR(64),
         post      STRING,
         phone1    VARCHAR(64),
         phone2    STRING,
         email     STRING,
         web       STRING
         )
       COMMENT 'A bucketed sorted user table'
         PARTITIONED BY (country VARCHAR(64))
       CLUSTERED BY (state) SORTED BY (city) INTO 32 BUCKETS
         STORED AS SEQUENCEFILE;
 
set hive.enforce.bucketing = true;
INSERT OVERWRITE TABLE bucketed_user PARTITION (country)
       SELECT  firstname ,
                   lastname  ,
                   address   ,
               city      ,
               state     ,
                   post      ,
                   phone1    ,
                   phone2    ,
                   email     ,
                   web       ,
                   country   
          FROM temp_user;

如何确定分桶数

分桶数的确定要结合和两点:

1,分桶的列基数要大,也即是该列去重后的值要大。

3,每个桶数据文件不能太小也不能太大。比如,如果block大小是256MB,那么使每个桶512 MB,是个不错的选择。

强调一下,为了正确的加载数据,需要将reduce数目和分桶数一样。设置方法如上。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 浪尖聊大数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档