Job执行优化
1 Explain
1.1 语法
EXPLAIN [FORMATTED|EXTENDED|DEPENDENCY|AUTHORIZATION|] query
FORMATTED:对执行计划进行格式化,返回JSON格式的执行计划
EXTENDED:提供一些额外的信息,比如文件的路径信息
DEPENDENCY:以JSON格式返回查询所依赖的表和分区的列表
AUTHORIZATION:列出需要被授权的条目,包括输入与输出
1.2 组成
执行计划一般由三个部分构成,分别是:
1)The Abstract Syntax Tree for the query
抽象语法树:Hive使用Antlr解析生成器,可以自动地将HQL生成为抽象语法树
2)The dependencies between the different stages of the plan
Stage依赖关系:会列出运行查询所有的依赖以及stage的数量
3)The description of each of the stages
Stage内容:包含了非常重要的信息,比如运行时的operator和sort orders等具体的信息
1.3 示例
explain
select
deptno,count(*) as cnt
from tb_emp where salary > 2000
group by deptno order by cnt desc;
2 MapReduce属性优化
2.1 本地模式
-
本地计算模式,允许程序不提交给YARN,直接在本地运行,以便于提高小数据量程序的性能。
-
set hive.exec.mode.local.auto = true;
-
本地模式做了以下限制,如果以下任意一个条件不满足,那么即使开启了本地模式,将依旧会提交给YARN集群运行
1)处理的数据量不超过128M
2)MapTask的个数不超过4个
3)ReduceTask的个数不超过1个
2.2 JVM重用
JVM实例在同一个job中重新使用N次,当一个Task运行结束以后,JVM不会进行释放,而是继续供下一个Task运行,直到运行了N个Task以后,就会释放
-- Hadoop3之前的配置,在mapred-site.xml中添加以下参数
-- Hadoop3中已不再支持该选项
mapreduce.job.jvm.numtasks=10
2.3 并行执行
当多个Stage之间没有依赖关系时,允许多个Stage并行执行,提高性能
-- 开启Stage并行化,默认为false
SET hive.exec.parallel=true;
-- 指定并行化线程数,默认为8
SET hive.exec.parallel.thread.number=16;
3 Join优化
Join方案 | 应用场景 | 原理 | 使用 |
---|---|---|---|
Map Join | 小表join大表 | 小表join小表 | 小表加载到MapTask的内存,底层无需经过shuffle | – 默认已经开启了Map Join hive.auto.convert.join=true |
Reduce Join | 大表join大表 | 两表数据在shuffle阶段分组后合并 | 不满足Map Join改为自动执行Reduce Join |
Bucket Join | 大表join大表 | 桶与桶之间关联,减少了比较次数 | 开启分桶join | 开启分桶SMB join |
4 优化器
4.1 关联优化
在Hive中开启关联优化,对有关联关系的操作进行解析时,可以尽量放在同一个MapReduce中实现
set hive.optimize.correlation=true;
4.2 CBO优化器引擎
很明显CBO引擎更加智能,所以在使用Hive时,我们可以配置底层的优化器引擎为CBO引擎。
-- 配置
set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;
5 谓词下推
- Inner Join和Full outer Join,条件写在on后面,还是where后面,性能上面没有区别
- Left outer Join时 ,右侧的表写在on后面,左侧的表写在where后面,性能上有提高
- Right outer Join时,左侧的表写在on后面、右侧的表写在where后面,性能上有提高
- 如果SQL语句中出现不确定结果的函数,也无法实现下推
6 数据倾斜
面对Join产生的数据倾斜,我们核心的思想是尽量避免Reduce Join的产生,优先使用Map Join来实现,但往往很多的Join场景不满足Map Join的需求
方案一:提前过滤,将大数据变成小数据,实现Map Join
方案二:使用Bucket Join
方案三:使用Skew Join
原理:
- 将Map Join和Reduce Join进行合并
- 如果某个值出现了数据倾斜,就会将产生数据倾斜的数据单独使用Map Join来实现,其他没有产生数据倾斜的数据由Reduce Join来实现,这样就避免了Reduce Join中产生数据倾斜的问题
- 最终将Map Join的结果和Reduce Join的结果进行Union合并
配置:
-- 开启运行过程中skewjoin
set hive.optimize.skewjoin=true;
-- 如果这个key的出现的次数超过这个范围
set hive.skewjoin.key=100000;
-- 在编译时判断是否会产生数据倾斜
set hive.optimize.skewjoin.compiletime=true;
-- 不合并,提升性能
set hive.optimize.union.remove=true;
-- 如果Hive的底层走的是MapReduce,必须开启这个属性,才能实现不合并
set mapreduce.input.fileinputformat.input.dir.recursive=true;