专栏首页Spark学习技巧浪尖,请问如何确定hive分桶数?

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

今日,有人在星球问了一个比较好的问题:浪尖,请问如何确定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数目和分桶数一样。设置方法如上。

本文分享自微信公众号 - Spark学习技巧(bigdatatip)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Hive性能优化(全面)

    面对这些问题,我们能有哪些有效的优化手段呢?下面列出一些在工作有效可行的优化手段:

    Spark学习技巧
  • Spark Adaptive Execution调研

    本文阅读价值不错建议大家仔细阅读,感谢作者疯狂哈秋,转自:https://blog.csdn.net/u013332124/article/details/90...

    Spark学习技巧
  • RocketMQ 在联想大数据中的应用简析

    众所周知,RocketMQ 作为一款分布式、队列模型的消息中间件,具有以下特点:

    Spark学习技巧
  • 基于 Go 语言开发在线论坛(二):通过模型类与MySQL数据库交互

    在这篇教程中,我们将在 MySQL 中创建一个 chitchat 数据库作为论坛项目的数据库,然后在 Go 项目中编写模型类与之进行交互。你可以本地安装 MyS...

    学院君
  • TensorFlow新功能「AutoGraph」:将Python转换为计算图

    昨天,TensorFlow推出了一个新功能「AutoGraph」,可以将Python代码(包括控制流print()和其他Python原生特性)转换为Tensor...

    量子位
  • TensorFlow发布重要更新AutoGraph,自动将Python转化为TF计算图

    作者:Alex Wiltschko、Dan Moldovan、Wolff Dobson

    机器之心
  • 目标追踪算法研究索引

    1. YaqiLYU在知乎问题【计算机视觉中,目前有哪些经典的目标跟踪算法?】下的回答

    jerrypxiao
  • NodeJS人脸识别(2)

    上一篇介绍了NodeJS实现人脸识别中的人脸注册,搜索,检测功能。可以看到其实抛开用户量不说,其实任何想要实现的功能最终用NodeJS都是可以实现的。今天我们来...

    逆月翎
  • 小米科技面试全过程

    一面(60min左右) 我是请学长内推的小米机器学习算法岗,一面面试官还是根据我的简历和我聊了会本科到研究生的个人经历,包括保研,成绩,比赛,实践经验都很详细的...

    牛客网
  • Errata in Effective Java Second Edition 博客分类: Java JavaSUNHTML

    exception’s detail method should indicate which invariant is violated (Item 63)....

    阿敏总司令

扫码关注云+社区

领取腾讯云代金券