Buckets On Hive

本文介绍了Hive中的分区与分桶技术,这两种技术可以提升查询效率。分区是根据数据字段创建目录,而分桶则是依据字段在特定目录下创建文件,用于加速单表和关联查询。创建分桶的语法、实例以及相关配置参数如`hive.enforce.bucketing`和`mapreduce.job.reduces`进行了展示。分桶插入数据时,需要考虑数据预处理和插入方式。通过设置`hive.enforce.bucketing`,可以实现数据的正确分桶。

序言

分区与分桶都是为了提升Hive的查询效率.两者也可以同时存在.也可以独立存在.具体可以根据自己的业务情况进行选择,创建不同类型的表.

  1. 分区是根据数据某一个字段新建一个目录.以增加相同数据的查询效率.
  2. 分桶是根据数据的某一个字段,在分区或者根目录下创建一个文件,多少个文件就是分桶数.同样可以提升单表查询的效率,另外如果是关联查询,则也会提升关联查询的效率.因为根据关联字段查找对应的文件就行了.cuiyaonan2000@163.com

创建分桶

创建的语法如下:

CREATE [EXTERNAL] TABLE <table_name>
    (<col_name> <data_type> [, <col_name> <data_type> ...])]
    [PARTITIONED BY ...] 
    CLUSTERED BY (<col_name>) 
        [SORTED BY (<col_name> [ASC|DESC] [, <col_name> [ASC|DESC]...])] 
        
        INTO <num_buckets> BUCKETS  
        
    [ROW FORMAT <row_format>] 
    [STORED AS TEXTFILE|ORC|CSVFILE]
    [LOCATION '<file_path>']    
    [TBLPROPERTIES ('<property_name>'='<property_value>', ...)];

举例:


-- sorted by 桶内的数据排序,可以有多个
-- clustered by 根据哪一个字段进行分桶
-- Distribute by 如果分桶跟排序的字段不一样则使用它来分桶
-- 分桶只能是一个字段.
create table student(id int,name string,sex int)
clustered by(id) 
sorted by(id DESC)
into 4 buckets
row format delimited
fields terminated by ',';

查看分桶信息

desc formatted 表名



相关配置

hive-site.xml

#让hive强制分桶,自动按照分桶表的bucket进行分桶 推荐使用
hive.enforce.bucketing : true;


#手动指定reduce数量,reduce数量也就是分桶数量,在没有设置分桶数量的时候默认的值
mapreduce.job.reduces : num;



#注意
hive.enforce.bucketing为true时,reduce要设为-1;
hive.enforce.bucketing为false时,reduce要设为和分桶数一致;
如果bucketing为 true,reduce又设成大于1的输,会执行两个job。

Insert Data

分桶的实质就是对 分桶字段做了hash,然后跟分桶数取余,已决定放入到哪个桶里(或者叫文件中cuiyaonan2000@163.com).

所以说如果原有数据没有按key hash ,需要在插入分桶的时候hash.同理通过load添加的数据是无法进行分桶的,因为没有进行key hash以及取余

hive.enforce.bucketing:true

在这种情况下我们可以直接使用hive所支持的insert方式进行数据插入

hive.enforce.bucketing:false

即设置了mapreduce.job.reduces:数字时.则要求hive所支持的insert后的select 中加入

增加增加CLUSTER BY 语句.因为插入的数据我们需要决定放入到哪个桶中.

<think>嗯,用户想了解Hive on Spark中如何避免数据倾斜问题,这需要结合多个优化策略来解决。从用户提供的引用资料来看,数据倾斜主要出现在分组聚合Join操作中,解决方案涉及参数调整、SQL重写特殊算法应用。 用户可能正在处理大规模数据作业,遇到了任务卡顿或OOM问题。ta的引用[3][4]明确提到了Executor丢失单个Task执行过久的现象,这是典型的数据倾斜症状。需要给ta既讲原理又给实操方案。 先梳理核心优化方向:分组聚合倾斜可以通过map端预聚合倾斜键分离处理;Join倾斜则重点考虑Map JoinJoin。用户引用[2]的第六章详细讨论了Sort Merge Bucket Map Join,这个高级特性值得重点说明。 参数配置方面,要强调几个关键点:skewjoin参数必须开启,reduce并行度要合理增加,小文件合并能预防倾斜恶化。用户引用[1]的Cloudera文档提到hive.optimize.skewjoin.compiletime参数,这个对静态数据倾斜特别有效。 特别要注意的是,用户引用[4]的Spark UI诊断方法很实用,应该纳入回答。当看到某个stage里个别task运行时间远超其他时,基本可以锁定倾斜发生在该shuffle阶段。 最后给出具体示例很重要,比如用distribute by rand()分散倾斜键的方法,用户引用[3]的第六条也提到reduce数量设置。示例代码要展示如何将倾斜键打散再聚合,这种实战方案最能解决用户痛点。</think>在 Hive on Spark 中优化数据倾斜问题,需要结合配置调整、SQL 改写特定算法。以下是关键优化方法: --- ### **一、分组聚合导致的数据倾斜优化**[^2][^3] 1. **Map 端预聚合** 启用 `hive.map.aggr = true`,减少 Shuffle 数据量。 2. **倾斜键分离处理** 将热点 key 单独提取处理,再合并结果: ```sql -- 1. 处理非倾斜数据 SELECT key, sum(value) FROM table WHERE key NOT IN ('hot_key1', 'hot_key2') GROUP BY key; -- 2. 单独处理倾斜 key SELECT 'hot_key1' AS key, sum(value) FROM table WHERE key = 'hot_key1' UNION ALL SELECT 'hot_key2' AS key, sum(value) FROM table WHERE key = 'hot_key2'; ``` 3. **随机数打散** 对倾斜 key 添加随机后缀,分散计算压力: ```sql SELECT split(key, '_')[0] AS key, sum(value) FROM ( SELECT concat(key, '_', cast(rand()*10 as int)) AS key, value FROM table ) tmp GROUP BY key; ``` --- ### **二、Join 操作导致的数据倾斜优化**[^2][^3][^4] 1. **Map Join 强制广播小表** 自动触发条件:小表 < `hive.auto.convert.join.noconditionaltask.size`(默认 10MB)。 手动指定: ```sql SELECT /*+ MAPJOIN(small_table) */ ... FROM big_table JOIN small_table ON ...; ``` 2. **倾斜键分离 + Map Join** 分离大表倾斜 key,小表拆分后分别 Join: ```sql -- 1. 提取大表热点 key 数据 CREATE TABLE skewed_data AS SELECT * FROM big_table WHERE key IN ('hot_key1', 'hot_key2'); -- 2. 非热点数据使用普通 Join SELECT ... FROM big_table b JOIN small_table s ON b.key = s.key WHERE b.key NOT IN ('hot_key1', 'hot_key2'); -- 3. 热点数据 + 拆分后的小表使用 Map Join SELECT /*+ MAPJOIN(sub_s) */ ... FROM skewed_data b JOIN (SELECT * FROM small_table WHERE key IN ('hot_key1','hot_key2')) sub_s ON ...; ``` 3. **Sort Merge Bucket Map Join (SMB Join)**[^2] **适用场景**:大表间 Join,且表已分排序。 **步骤**: ```sql -- 创建分排序表 CREATE TABLE bucketed_table CLUSTERED BY (key) SORTED BY (key) INTO 32 BUCKETS; -- 启用 SMB Join SET hive.optimize.bucketmapjoin = true; SET hive.optimize.bucketmapjoin.sortedmerge = true; ``` --- ### **三、关键参数配置**[^1][^2][^3] ```sql -- 通用倾斜优化 SET hive.optimize.skewjoin = true; -- 开启 Join 倾斜处理 SET hive.skewjoin.key = 100000; -- 超过此值视为倾斜 key SET hive.skewjoin.mapjoin.map.tasks = 10000; -- 处理倾斜的 Map Task 数 SET hive.skewjoin.mapjoin.min.split = 33554432; -- 最小分片大小 (32MB) -- 增加并行度 SET spark.sql.shuffle.partitions = 200; -- 调整 Shuffle 分区数 SET mapreduce.job.reduces = 100; -- 设置 Reduce 数量 -- 内存优化 (防 OOM) SET spark.executor.memory = 8g; -- Executor 堆内存 SET spark.yarn.executor.memoryOverhead = 2g; -- 堆外内存 ``` --- ### **四、其他优化技巧** 1. **小文件合并** 减少 Map Task 负载: ```sql SET hive.merge.mapfiles = true; -- Map 输出合并 SET hive.merge.sparkfiles = true; -- Spark 输出合并 SET hive.merge.size.per.task = 256000000; -- 合并文件大小 (256MB) ``` 2. **动态分区优化** 避免分区过多导致元数据压力: ```sql SET hive.exec.dynamic.partition.mode = nonstrict; SET hive.exec.max.dynamic.partitions = 10000; ``` --- ### **诊断数据倾斜方法**[^4] 1. **Spark UI 观察** - 检查 Stage 中是否有 **少数 Task 处理时间远高于其他**。 - 查看 **Shuffle Read/Write 数据量分布**,是否严重均。 2. **日志分析** 出现 `ExecutorLostFailure` 或 `OOM` 错误时,大概率是倾斜导致。 --- ### **示例:Join 倾斜优化前后对比** **原始 SQL** (易倾斜): ```sql SELECT a.*, b.* FROM big_table a JOIN small_table b ON a.key = b.key; ``` **优化后 SQL** (分离热点 key): ```sql -- 提取热点 key 列表 (如出现频率 > 10万次) CREATE TABLE hot_keys AS SELECT key FROM big_table GROUP BY key HAVING count(1) > 100000; -- 非热点数据 Join SELECT a.*, b.* FROM big_table a JOIN small_table b ON a.key = b.key WHERE a.key NOT IN (SELECT key FROM hot_keys) UNION ALL -- 热点数据 + Map Join SELECT /*+ MAPJOIN(b) */ a.*, b.* FROM big_table a JOIN small_table b ON a.key = b.key WHERE a.key IN (SELECT key FROM hot_keys); ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cuiyaonan2000

给包烟抽吧

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

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

打赏作者

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

抵扣说明:

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

余额充值