Hive分桶之BUCKET详解

本文介绍了Hive中分桶的概念及其实现原理,探讨了如何通过分桶提高查询处理效率和取样的有效性,并通过实例展示了分桶的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。 
②显式原始文件时,因为分隔字符是一个不能打印的控制字符,因此字段都挤在一起。 
<think>好的,我现在需要回答用户关于Hive中创建表时如何使用多个字段的问题。用户还提到是否需要在建表语句中指定字段。首先,我得回顾一下之前提供的引用内容,看看有没有相关信息。用户之前的引用[1]和[2]中提到了表的建表语法,使用了CLUSTEREDBY子句,并指定了一个字段,比如id。这说明字段是需要显式声明的。但用户现在的问题是多个字段,这可能需要确认Hive是否支持多个字段,以及语法是怎样的。我需要查阅Hive的官方文档或者可靠资料,确认是否支持多字段。根据以往的知识,Hive允许在CLUSTERED BY后面指定多个字段,用逗号隔。例如,CLUSTEREDBY (col1, col2)。然后的数量还是用INTO... BUCKETS来指定。这个过程是基于多个字段的组合哈希值来的,这样可以更细致地数据。接下来,用户询问是否必须要在建表语句中指定字段。根据之前的回答,表必须指定,否则就不是表。所以如果用户想创建表,字段是必须的,无论是单个还是多个字段。如果不需要,就不需要这个子句。 然后,我需要考虑如何编写示例代码。用户提供的引用中的例子都是单个字段,比如CLUSTEREDBY (id),所以多个字段的情况应该是类似的,比如CLUSTERED BY(id, name)。同时,可能还需要注意字段的顺序和类型,以及数量的影响。 另外,用户可能想知道使用多个字段的实际应用场景。比如,当单个字段的无法有效避免数据倾斜,或者查询经常涉及多个字段的组合时,使用多字段可能更有效。这时候需要举一个例子,比如按部门和职位,优化涉及这两个字段的JOIN操作。 还需要注意表的写入方式,必须通过INSERTOVERWRITE来确保数据正确,直接加载文件可能不会触发过程。这点在之前的引用中提到过,需要再次强调,尤其是在多字段的情况下。 最后,生成相关问题,可能需要包括字段选择策略、多字段的性能影响,以及如何验证多字段是否正确等。这些问题可以帮助用户进一步理解表的应用和优化。</think>### Hive表多字段语法及用法详解 --- #### **1. 多字段的语法规则** 在Hive中,**支持指定多个字段作为字段**,语法需在 `CLUSTERED BY` 子句中用逗号隔多个字段,并明确数量。完整语法如下: ```sql CREATE TABLE table_name ( column1 data_type, column2 data_type, ... ) CLUSTERED BY (col1, col2) INTO N BUCKETS -- 多字段 [ROW FORMAT ...]; ``` **示例**: ```sql CREATE TABLE user_bucketed ( user_id STRING, dept STRING, salary INT ) CLUSTERED BY (dept, user_id) INTO 8 BUCKETS -- 按部门和用户ID STORED AS ORC; ``` **关键点**: - **逻辑**:Hive会计算所有字段的联合哈希值,再按数取模数据中[^2]。 - **字段顺序**:字段的顺序会影响数据布,例如 `(dept, user_id)` 和 `(user_id, dept)` 的哈希结果不同。 --- #### **2. 是否需要显式指定字段?** **必须指定**。若需创建表,必须在建表语句中通过 `CLUSTERED BY` 明确字段(单字段或多字段),否则Hive不会自动。 - **普通表**:无需 `CLUSTERED BY` 子句。 - **表**:必须包含 `CLUSTERED BY` 和 `INTO ... BUCKETS`。 --- #### **3. 多字段的应用场景** 1. **优化多字段JOIN**: 若查询中频繁使用 `dept` 和 `user_id` 组合进行JOIN,可减少Shuffle数据量,提升性能[^2]。 2. **避免数据倾斜**: 单字段可能因哈希冲突导致倾斜,多字段组合可降低冲突概率。 3. **精细化数据布**: 例如按 `(地区, 产品类别)` ,便于按组合条件快速筛选数据。 --- #### **4. 数据写入注意事项** - **必须通过INSERT写入**: 表需通过 `INSERT OVERWRITE/INTO` 写入数据才能触发逻辑,直接使用 `LOAD DATA` 不会[^2]。 - **排序支持**: 可结合 `SORTED BY` 对数据排序(需Hive 2.0+),例如: ```sql CLUSTERED BY (dept) SORTED BY (salary DESC) INTO 4 BUCKETS ``` --- #### **5. 多字段的验证方法** 1. **查看文件结构**: 表每个对应一个文件,可通过HDFS路径检查文件数量是否符合数。 2. **执行抽样查询**: 使用 `TABLESAMPLE` 验证数据布: ```sql SELECT * FROM user_bucketed TABLESAMPLE(BUCKET 1 OUT OF 8 ON dept, user_id); ``` --- ### 示例:完整多字段表定义 ```sql CREATE EXTERNAL TABLE sales_bucketed ( order_id STRING, product_id STRING, region STRING ) PARTITIONED BY (dt STRING) -- 区字段 CLUSTERED BY (region, product_id) INTO 16 BUCKETS -- 多字段 STORED AS ORC LOCATION '/hive/sales_bucketed'; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值