本文介绍有关hive的调优策略。
explain执行计划
通过explain关键字,可以详细地表示出执行语句所对应的MapReduce代码,语法格式如下:
explain [extended|dependency|authorization] query
理解Hive对每个查询进行解析和计划的复杂细节,对于分析复杂的或者效率低下的查询时非常不错的方式。我们可以在不执行真正的SQL之前观察查询计划来了解HQL(Hive QL)语句的执行过程。
并行执行
Hive会将一个HQL语句转换成一个或者多个执行Stage。默认情况下,Hive一次只会执行一个Stage。但是在一些情况下,某个特定的作业可能包含多个Stage,而且多个Stage之间并不存在依赖关系,也就是说这些Stage是可以并行执行的,这样并行度提高之后将使得整个作业的执行时间缩短。在Hive中我们可以通过设置参数来达到并行执行Stage的目的,设置方式如下:
# 打开任务并行执行
set hive.exec.parallel=true;
# 设置同一个sql允许的最大并行度,默认是8
set hive.exec.parallel.thread.number=16;
JVM重用
由于Hive是基于MapReduce的,所以JVM重用对于Hive作业的性能也是至关重要的,特别是针对很难避免小文件的场景或者任务特别多的场景,JVM重用特别有效。
MapReduce默认为每个map和reduce任务都开启一个新的JVM来执行,这时JVM在启动和销毁时可能会造成相当大的开销,尤其是在执行的作业包含成百上千个任务的情况下。JVM重用使得一个JVM实例可以在同一个作业中重复使用N次,N的值可以在Hadoop的mapre-site.xml文件中进行设置。
<property>
<name>mapred.job.reuse.jvm.num.tasks</name>
<value>10</value>
</property>
也可以在Hive的执行中设置:
set mapred.job.reuse.jvm.num.tasks=10;
推测执行
同JVM重用一样,推测执行也是MapReduce作业的一个特性。
Haoop的推测执行功能通过如下两个参数在mapred-site.xml中控制:
<property>
<name>mapred.map.tasks.speculative.execution</name>
<value>true</value>
</property>
<property>
<name>mapred.reduce.tasks.speculative.execution</name>
<value>true</value>
</property>
Hive的推测功能也可以通过如下设置使其生效:
set hive.mapred.map.tasks.speculative.execution=true;
set hive.mapred.reduce.tasks.speculative.execution=true;
列裁剪
Hive在读数据的时候,可以只读取查询中所需要用到的列,而忽略其他列。
裁剪所对应的参数项为:
# 默认值为真
hive.optimize.cp=true
GROUP BY操作
进行group by操作时需要注意以下几点:
(1)map端部分聚合:事实上并不是所有的聚合操作都需要在reduce部分进行,很多聚合操作都可以先在map端进行部分聚合,然后再在reduce端得出最终结果。这里需要修改的参数为:
# 用于设定是否在map端进行聚合,默认值为真
hive.map.aggr=true
# 用于设定map端进行聚合操作的条目数
hive.groupby.mapaggr.checkinterval=100000
(2)有数据倾斜时进行负载均衡:此处需要设定:
hive.groupby.skewindata
当选项设定为true时,生成的查询计划有两个MapReduce任务。在第一个MapReduce任务中,map的输出结果集合会随机分布到reduce中,每个reduce做部分聚合操作并输出结果。这用处理的结果是,相同的Group By Key有可能分发到不同的reduce中,从而达到负载均衡的目的。第二个MapReduce任务再根据预处理的数据结果按照Group By Key分布到reduce中(这个过程可以保证相同的Group By Key分布到同一个reduce中),最后完成最终的聚合操作。
合并小文件
文件很小但是数量很多时容易在文件存储端造成瓶颈,给HDFS带来压力,影响处理效率。为此,可以通过合并Map和Reduce的结果文件来消除这样的影响。用于设置黑帮属性的参数有:
# 是否合并map端输出文件(默认值为真)
hive.merge.mapfiles=true
# 是否合并reduce端输出文件(默认值为假)
hive.merge.mapredfiles=false
# 合并文件的大小
hive.merge.size.per.task=256*1000*1000(默认值为256000000)
设置合适的reduce个数
reduce个数的设定将极大地影响人物的执行效率,在不指定reduce个数的情况下,Hive会基于以下两个参数来猜测reduce个数:
# 每个reduce任务处理的数据量,默认为1000^3=1GB
hive.exec.reducers.bytes.per.reducer
# 每个任务最大的reduce数,默认为999
hive.exec.reducers.max
计算reduce个数的公式很简单:N=min(参数2,总输入数据量/参数1),如果reduce的输入(map的输出)总大小不超过1GB,那么只会有一个reduce任务。
(1)调整reduce个数方法一:调整参数值:
set hive.exec.reducers.bytes.per.reducer=500000000;(500MB)
(2)调整rduce个数方法二:
set mapred.reduce.tasks=15;
ps:望多多支持,后续更新中。。。