Hive 调优总结...持续更新

本文详细介绍了Hive的性能调优策略,包括Fetch抓取、本地模式、Join优化(如MapJoin、Bucket-MapJoin、SMBJoin)、数据倾斜处理、SQL优化、动态分区、并行执行以及其他高级优化技巧。通过这些方法,可以显著提高Hive查询的效率和系统的整体性能。

Fetch抓取(Hive可以避免进行MapReduce)

Fetch 抓取说明

Hive 中对某些情况的查询可以不必使用 MapReduce 计算

例如:select * from employees; 在这种情况下,Hive 可以简单地读取 employee 对应的存储目录下的文件,然后输出查询结果到控制台

hive-default.xml.template 文件中 hive.fetch.task.conversion 默认是 more ,老版本 hive 默认是 minimal ,该属性修改为 more 以后,在全局查找、字段查找、limit 查找等都不走 mapreduce

Fetch 抓取设置

# 查询语句,都会执行 mapreduce 程序
set hive.fetch.task.conversion=none;

# 查询方式都不会执行 mapreduce 程序
set hive.fetch.task.conversion=more;
本地模式

本地模式说明

多数的 Hadoop Job 是需要 Hadoop 提供的完整的可扩展性来处理大数据集的

不过,有时 Hive 的输入数据量是非常小的,在这种情况下,为查询触发执行任务时消耗可能会比实际 job 的执行时间要多的多

对于大多数这种情况,Hive 可以通过本地模式在单台机器上处理所有的任务,对于小数据集,执行时间可以明显被缩短。

本地模式的开启

--开启本地 mr
set hive.exec.mode.local.auto=true;  

--设置local mr的最大输入数据量,当输入数据量小于这个值时采用local  mr的方式,默认为134217728,即128M
set hive.exec.mode.local.auto.inputbytes.max=51234560;

--设置local mr的最大输入文件个数,当输入文件个数小于这个值时采用local mr的方式,默认为4
set hive.exec.mode.local.auto.input.files.max=10;
Join 优化
关联优化器

关联优化器说明

在 Hive 的一些复杂关联查询中,可能同时还包含有 group by 等能够触发 shuffle 的操作,有些时候 shuffle 操作是可以共享的,通过关联优化器选项,可以尽量减少复杂查询中的 shuffle,从而提升性能

-- 开启关联优化器
set hive.optimize.correlation=true;
Map 端 Join 优化(大表 Join 小表)

什么是 MapJoin

在 Map 阶段进行表之间的连接,而不需要进入到 Reduce 阶段才进行连接,这样就节省了在 Shuffle 阶段时要进行的大量数据传输,从而起到了优化作业的作用

MapJoin 使用的场景

① 条件一:一份表的数据分布在不同的Map中
② 条件二:其他连接的表的数据必须在每个 Map 中有完整的拷贝
在两个要连接的表中,一个是大表,另外一个是小表,且小表的数据可以放在内存中而不影响性能,这样我们就把小表文件复制到每一个Map任务的本地,再让Map把文件读到内存中待用

优化说明

如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么 Hive 解析器会将 Join 操作转换成 Common Join ,即:在 Reduce 阶段完成 join ,容易发生数据倾斜

可以用 MapJoin 把小表全部加载到内存 ,在 map 端进行 join ,避免 reducer 处理

优化执行过程

① TaskA

通过 MapReduce Local Task ,将小表读入内存,转换为 HashTable 数据结构,写入到本地文件中 HashTableFiles ,然后加载到 Distributed Cache

② TaskB

启动 MapTasks 扫描大表 a , 在 Map 阶段,根据 a 的每一条记录去和 DistributeCacheb 表对应的 HashTable 关联,由于 MapJoin 没有 Reduce ,也就是在 Map 阶段完成 Join ,然后直接输出结果

map 端的 join 参数配置

① 设置自动选择 mapjoin

-- 默认为true
set hive.auto.convert.join = true; 

② 表文件的大小作为开启 MapJoin 的阈值

-- 旧版本
-- 小表的输入文件大小的阈值(以字节为单位)
-- 如果文件大小小于此阈值,它将尝试将 common join 转换为 map join
-- 在实际使用中,只要根据业务把握住小表的阈值标准即可,hive 会自动帮我们完成 mapjoin,提高执行的效率
-- 如果 hive.auto.convert.join = false ,则该参数配置不生效
set hive.mapjoin.smalltable.filesize= 25000000;

-- 新版本
-- 如果参与连接的 N 个表(或分区) 中的 N-1 个的总大小小于 512MB ,则自动转为 MapJoin
-- 默认值为 20MB
set hive.auto.convert.join.noconditionaltask.size=512000000

MapJoin 使用案例

-- A 表有 100 条记录,B 表有 100w 条记录

-- 优化前
-- B 表的数据倾斜比较严重,某个 key 有 30w 条记录,运行过程中很慢,且 reduce 阶段运行时间过长或内存不够
select f.a,f.b from A t join B f  on ( f.a=t.a and f.ftime=20110802)  

-- 优化后
-- 通过 MapJoin 在 Map 阶段做了 join 操作,reduce 阶段的效率就会提高
-- 在 hive 0.7 之前需要通过改种方式才能使 MapJoin 生效,hive 0.7 之后会自动完成 MapJoin
select /*+ mapjoin(A)*/ f.a,f.b from A t join B f  on ( f.a=t.a and f.ftime=20110802) 
Bucket-MapJoin

什么是 Bucket-MapJoin

两个表 Join 的时候,小表不足以放到内存中,但是又想用 map side join ,这个时候就要用到 bucket Map join

Bucket-MapJoin 使用的条件

① set hive.optimize.bucketmapjoin = true;

② 一个表的 bucket 数是另一个表 bucke t数的整数倍

③ bucket列 == join列

④ 必须是应用在 map join 的场景中,如果表不是 bucket 的,则只是做普通 join

Bucket-MapJoin 的使用

两个 join 表在 join key 上都做 hash bucket ,并且把你打算复制的那个(相对)小表的 bucket 数设置为大表的倍数。这样数据就会按照 key join ,做 hash bucket 。小表依然复制到所有节点,Map join 的时候,小表的每一组 bucket 加载成 hashtable ,与对应的一个大表 bucket 做局部 join ,这样每次只需要加载部分 hashtable 就可以了

-- 小表
create table testA(imei string,sndaid string,data_time string) clustered BY(imei) SORTED BY(imei) INTO 10 BUCKETS;

-- 大表
create table testB(imei string,sndaid string,data_time string) clustered BY(imei) SORTED BY(imei) INTO 5 BUCKETS;

-- 开启 Bucket-MapJoin
set hive.optimize.bucketmapjoin = true;
-- 查询
select /*+ mapjoin(b) */ count(1) from testA a join testB b on a.imei = b.imei  
Sort Merge Bucket Join (SMB Join)

什么是 SMB Join

大表对小表应该使用 MapJoin 来进行优化,但是如果是大表对大表,如果进行 shuffle ,那就非常可怕,第一个慢不用说,第二个容易出异常,此时就可以使用 SMB Join 来提高性能。SMB Join 基于 bucket-mapjoin有序bucket ,可实现在 map 端完成 join 操作,可以有效地减少或避免 shuffle 的数据量,SMB join 的条件和 Map join 类似但又不同

SMB Join 的使用条件

bucket mapjoin SMB join
set hive.optimize.bucketmapjoin = true; set hive.optimize.bucketmapjoin = true;
set hive.auto.convert.sortmerge.join=true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;
一个表的bucket数是另一个表bucket数的整数倍 小表的 bucket 数 = 大表 bucket 数
bucket列 == join列 Bucket 列 == Join 列 == sort 列
必须是应用在map join的场景中 必须是应用在bucket mapjoin 的场景中

确保同列排序

hive 并不检查两个 join 的表是否已经做好 bucketsorted ,需要用户自己去保证 join 的表数据 sorted,否则可能数据不正确

# 办法一: 开启强制排序,插数据到表中会进行强制排序,默认false
hive.enforce.sorting = true

# 办法二:插入数据时通过在sql中用
distributed c1 sort by c1 或者 cluster by c1

SMB Join的使用

① 建表

-- 必须包含 CLUSTERED BY 和 SORTED BY
create table test_smb_2(mid string,age_id string)
CLUSTERED BY(mid) SORTED BY(mid) INTO 500 BUCKETS;

② 开启配置

--写入数据强制分桶
set hive.enforce.bucketing=true;
--写入数据强制排序
set hive.enforce.sorting=true;
--开启bucketmapjoin
set hive.optimize.bucketmapjoin = true;
--开启SMB Join
set hive.auto.convert.sortmerge
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值