大数据单机学习环境搭建(6)Hive优化实现

大数据单机学习环境搭建(6)Hive优化实现

1.表的设计优化

如果觉得这部分不好理解先看本人另外一篇文章 Hive建表DDL详解

1.1 表设计优化

1. 分区表设计及优化

减少全表扫描,hive会使用表的最后一级目录作为底层处理数据的输入

2. 分桶表设计及优化

==Bucket与Bucket做Join,不用全表join,不用shuffle,就可以在Map端做join,但前提是join字段是分桶字段,否则无效。==

注:解决大表Join时只能走ReduceJoin,不能MapJoin的问题。MapJoin要比ReduceJoin更高效,因为ReduceJoin要做全表shuffle。
缺点是表结构复杂,维护和写入耗时较长,但考虑到hive是olap,读的压力远大于写,所以分区和分桶仍有很强的实用性。

3. 文件格式优化

Hive数据存储的本质是HDFS,为了提高对HDFS文件读写的性能,Hive提供多种文件存储格式:TextFile、SequenceFile、ORC(优化后的列式记录)、Parquet等。==最推荐的是ORC,来源于Hive,且占用小、存储和查询效率都高;默认TextFile格式,如果要写入Parquet和ORC格式,不能load而是要insert。==

1.2表数据优化

4. 数据压缩

不同的压缩算法配合不同的文件格式使用,提升文件传输效率的同时要考虑压缩带来的时间成本(解压)和CPU成本,(Map阶段和Reduce阶段都会有大量数据传输),压缩算法要是Hadoop的压缩算法,如:Snappy、Lzo、Gzip等

5. 存储优化

存储优化——避免小文件生成
Hive存储本质是HDFS,HDFS是不利于小文件存储的,每个小文件产生一条元数据信息,并不利于用MapReduce处理,MapReduce中每个小文件会启动一个MapTask计算处理,导致资源的浪费。Hive中提供了一个特殊机制,可以自动判断是否是小文件,如果是小文件可以自动将小文件合并。

-- 如果hive程序,只有maptask,将MapTask产生的所有小文件进行合并
set hive.merge.mapfiles=true
-- 如果hive程序,有Map和ReduceTask,将reduceTask产生的小文件合并
set hive.merge.mapredfiles=true
-- 每一个合并的文件大小(244M)
set hive.merge.size.per.task=256000000;
-- 平均每个文件的大小,如果小于这个值就会进行合并(15M)
set hive.merge.smallfiles.avgsize=16000000;

存储优化——合并小文件
Hive中也提供一种输入类CombineHiveInputFormat,用于将小文件合并以后,再进行处理

-- 设置Hive中底层MapReduce读取数据的输入类,将所有文件合并为一个大文件作为输入
set hive.input.format-org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 

2.JOB任务优化

2.1 谓词下推(PDD)

SQL编写第一原则:不影响最终结果的情况下,尽可能将过滤条件提前执行,跳过无关数据,减少读取的数据量。增加分区条件,避免全表扫描就是这个道理。

Hive谓词下推是默认开启的,过滤条件下推到Map端,减少Map到reduce的传输数据,提升整体性能。

1.对于Join、Full Outer Join,条件写在on后还是where后,性能上没有区别
2.对于Left Join,右表写在on后、左表写在where后,性能上有提升。Right Join反之亦然。

简单示例

select a.id, b.name, b.age
from a left join b 
on a.id = b.id and b.sex='man' and b.age > 0
where a.dt = '20220510'
	and a.region='BJ'

2.2 Join方案优化

Join是SQL编写过程最常用的操作,SQL执行顺序join on排第一,对于SQL优化的重要性不言而喻,基本原则是避免笛卡尔积、小表join大表、join表的数据能少则少。

Hive中Join优化:Map Join适合小表Join大表,Reduce Join适合大表Join大表,过大的表使用Bucket Join
1)Map Join

应用场景:小表Join大表 或 小表Join小表
原理:Map端会把小表数据做Distributed Cache分布式缓存,把数据分别加载到各台机器上,再启动MapTask分别读大表的数据分别跟缓存之间进行关联,直接输出关联的结果。这个过程中MR阶段没有Reduce阶段,也就没有shuffle过程
使用:尽可能使用Map Join进行关联,Map Task读取大表时会按照数据量大小自动调整并发度。
-- Hive中默认自动开启Map Join:
hive.auto.convert.join=true
-- Hive中小表的大小限制
hive.auto.convert.join.noconditionaltask.size=512000000

2)Reduce Join

应用场景:适合于大表Join大表
原理:分别读取两张大表,将两张表的数据在shuffle阶段利用shuffle的分组将数据按照关联字段进行合并。
使用:Hive自动判断是否满足Map Join,如果不满足则自动执行Reduce Join。

3)Bucket Join

使用场景:适合于高频和较高频的大表Join大表
原理:将两张表按照相同的规则将数据划分,根据对应的规则的数据进行桶间Join而不是全表Join,减少笛卡尔积,减少了比较次数,提高了性能
使用1:Bucket Join,要求:分桶字段=Join字段,桶的个数相等或成倍数
使用2:Sort Merge Bucket Join (SMB),要求:分桶字段=Join字段=排序字段,桶的个数相等或成倍数。因为分桶字段还Sort By排序了,所以性能较Bucket Join更好。
-- 分桶join必须手动开启才能使用:
-- Bucket Join只要开启bucketmapjoin即可
set hive.optimize.bucketmapjoin=true;

-- SMB Join需要开启如下参数
set hive.optimize.bucketmapjoin=true;
set hive.auto.convert.sortmerge.join=true;
set hive.optimize.bucketmapjoin.sortedmerge=ture;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;

2.3 Explain解析命令

经验来讲,这个不可全信,有时候还是要结合实际脚本分区执行来锁定问题。

-- 查看MR执行流程
explain extended select * from db.table_name

2.4 数据倾斜

分布式计算中最常见、最容易遇到的问题——数据倾斜。
1)Group by过程数据倾斜
方案一:开启Map端聚合

-- 通过减少shuffle数据量和Reduce阶段的执行时间,避免每个Task数据差异过大导致数据倾斜
hive.map.aggr=true;

方案二:实现随机分区(优势也是劣势)

-- distribute by用于指定底层按照哪个字段作为key实现分区、分组等
-- 通过rank函数随机值实现随机分区,避免数据倾斜
select * from table distribute by rand();

方案三:数据倾斜时自动负载均衡

-- 开启该参数以后,当前程序会自动通过两个MapReduce来运行
-- 第一个MapReduce自动进行随机分布到Reduce中,每个Reduce做部分聚合操作,输出结果
-- 第二个MapReduce将上一步聚合的结果再按照业务(group by key)进行处理,保证相同的key分布到一起,最终聚合得到结果
hive.groupby.skewindata=true;

2)Join过程数据倾斜
Join操作两张大表时,无法实现Map Join,只能走Reduce Join,当关联字段中某一种值过多的时候依然会导致数据倾斜问题

方案一:尽量避免Reduce Join产生,优先使用Map Join实现(默认开启)
方案二:提前过滤,将大数据变成小数据,实现Map Join
方案三:使用Bucket Join,Hash值取模分桶可以有效避免数据倾斜
方案四:使用Skew Join,一种专门为了避免数据倾斜设计的特殊Join过程

Skew Join原理:将Map Join和Reduce Join进行合并,如果某个值出现数据倾斜,就会将产生数据倾斜的数据单独使用Map Join实现,其他没有产生数据倾斜的数据由Reduce Join实现,避免了Reduce Join中产生数据倾斜的问题,最终将Map Join的结果和Reduce Join的结果进行Union合并。

-- Skew Join的使用配置
-- 开启运行过程中skew join
set hive.optimize.skewjoin=true;
-- 如果这个key的出现次数超过这个范围
set hive.skewjoin.key=100000;
-- 在编译时判断是否会产生数据倾斜
set hive.optimize.skewjoin.compiletime=true;
-- 不合并,提升性能
set hive.optimize.union.remove=true;
-- 如果Hive的底层走的是MR,必须开启这个属性,才能实现不合并
set mapreduce.input.fileinputformat.input.dir.recursive=true;

2.5 MapReduce属性优化

1)本地模式和Yarn模式自动切换:满足数据量、任务数等不超过某一值时,任务不提交Yarn,而是本地执行

-- 开启本地模式:默认关闭,
set hive.exec.mode.local.auto=true;

2)JVM重用:Hadoop默认为每个Task启动一个JVM来运行,而JVM在启动时内存开销大;JVM重用可以使得JVM实例在同一个job中重新使用N次,当一个Task运行结束以后,JVM不会进行释放,而是继续供下一个Task运行,直到运行了N个Task以后释放,N通常设置在10-20之间。

-- Hadoop3中不再支持该选项,之前版本配置mapred-site.xml中添加一下参数
mapreduce.job.jvm.numtasks=10

3)并行执行:Hive在实现HQL计算运行时,会解析多个Stage,有些Stage有依赖关系只能挨个执行,也有很多没有依赖关系,可以并行执行提高性能,例如Union语句、Join语句等。

-- 开启Stage并行执行:默认关闭
SET hive.exec.parallel=true;
-- 指定并行化线程数,默认8
SET hive.exec.parallel.thread.number=16;

2.6 优化器

当一个程序中如果有一些操作彼此之间有关联性(相关性),可以只用一个MapReduce实现,但Hive不会自动优化,仍会分为多个MapReduce执行,导致性能相对较差。
例如同一个名为age的字段即做gruop by又做order by,完全可以在一次shuffle过程中完成,可以在一个MapReduce中实现,但Hive默认会在两个MapReduce分别做group by和order by两个操作

-- 开启关联优化,对有关联关系的操作进行解析,可以尽量在同一个MapReduce中实现(并不绝对会放在一起执行)。
set hive.optimize.correlation=true;

优化器引擎,RBO和CBO

1.默认RBO优化器(基于规则的优化器),跟据设定好的规则对程序进行优化
2.CBO优化器(基于代价的优化器),更加友好,根据不同场景所付出的代价来选择合适的优化方案。依赖于Analyze分析器。
3.Analyze分析器(CBO优化器的依赖)计算代价
-- CBO优化器开启
set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;

关于DQL的基础优化见 SQL的DQL查询优化

通过上述任务处理还是慢的话,考虑换spark引擎计算吧。当下离线任务项目中Spark的使用更常见,较MR有更多的算子,基于内存计算,有更多的优势,且支持多种运行模式,与Hive完美结合,后续将在Spark内容整理中详细解释。


声明:本文所载信息不保证准确性和完整性。文中所述内容和意见仅供参考,不构成实际商业建议,如有雷同纯属巧合。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值