Hive调优相关总结

前言

  • 我们都知道Hive默认的执行引擎是MR,在没有对Hive执行引擎改造之前(如HDP的TEZ,Hive on Spark项目),我们对Hive的调优依然只能围绕Hive本身支持的如存储格式,压缩,参数,SQL语句等方面的优化做出考虑。

存储与压缩

  • 关于Hive存储格式和压缩方式的选择和使用,这里就不再做介绍,请参考以前博客存储格式和压缩方式

Hive 调优参数

  • 因为Hive的默认执行引擎为MR,所以基于Hive的参数调优,主要还是MR的参数调优以及Hive客户端的一些设置

  • 1.开启Hive map阶段及reduce压缩参数
    在MR中使用压缩需要从输入,中间,输出三个阶段去选择不同的压缩方式,输入阶段可能更看重的是数据是否支持split,支持split可以增加Map输入个数而增加计算并行度,如选择可分割的Bzip2和Lzo(Lzo压缩格式要建立索引),中间map输出要考虑下阶段reduce输入带来的压缩与解压CPU时间开销,如选择压缩解压速率较快的Snappy,最终输出如果不作为其他依赖任务的输入,更加考虑的是磁盘存储上的开销,如选择高压缩比的Bzip2

开启map阶段使用压缩参数:

set hive.exec.compress.intermediate=true
set mapred.map.output.compression=true
set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.SnappyCodec

开启reduce最终输出使用压缩参数:

set hive.exec.compress.output=true 
set mapred.output.compression=true 
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
set mapred.output.compression.type=BLOCK
  • 2.设置Map与Reduce个数增加并行
    Map输入个数是根据split size大小来划分,默认是一个block块一个map,若单个文件小于一个block大小,那个也会作为一个map输入,MapReduce计算split size 大小是由computeSplitSize函数算出:

      protected long computeSplitSize(long blockSize, long minSize,
                                        long maxSize) {
          return Math.max(minSize, Math.min(maxSize, blockSize));
        }
    

    可以看出,当最大值设置大于一个块大小时,split size为一个block大小,若想增加map输入并行度,则需设置最大值小于一个block,反之,若想减少map输入并行度,则需设置最小值大于一个block大小

参数设置:

 set mapred.max.split.size=xxx
 set mapred.min.split.size=xxx
 set mapred.min.split.size.per.node=xxx
 set mapred.min.split.size.per.rack=xxx
 也可直接设置map数和reduce数
 set mapreduce.job.maps(mapred.map.tasks)=n
 set mapreduce.job.reduces(mapred.reduce.tasks)=n
 若不设置reduce个数,Hive将自己去计算Reduce个数(默认为-1),
 由以下参数控制:
 set hive.exec.reducers.bytes.per.reducer=xxx
 set hive.exec.reducers.max=n
  • 3.hive.fetch.task.conversion:
    fetch task 为执行hive时,不用执行MapReduce,如select * from emp;

参数设置:

Hive.fetch.task.conversion 默认为minimal
修改配置文件hive-site.xml

  hive.fetch.task.conversion
  more
  
    Some select queries can be converted to single FETCH task 
    minimizing latency.Currently the query should be single 
    sourced not having any subquery and should not have
    any aggregations or distincts (which incurrs RS), 
    lateral views and joins.
    1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
    2. more    : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns)
  
 
 
 或者当前session修改
hive> set hive.fetch.task.conversion=more;
执行SELECT id, money FROM m limit 10; 不走mr
  • 4.并行执行:
    并行执行一个作业的多个stage

参数设置:

set hive.exec.parallel=true
set hive.exec.parallel.thread.number=8
  • 5.JVM重用
    JVM重用对hive的性能具有非常大的 影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。jvm的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况

参数设置:

set mapred.job.reuse.jvm.num.tasks=n
  • 6.开启推测执行
    推测执行即一个map或reduce因为物理因素在某个节点执行的很慢,会在其他性能较好的节点启动一个相同的任务去执行,原有任务和新任务谁先执行完毕,就把较慢的kill掉

参数设置:

set mapreduce.map.speculative=true
set mapred.map.tasks.speculative.execution=true
set mapreduce.reduce.speculative=true
set mapred.reduce.tasks.speculative.execution=true
  • 7.启用map join:
    Map Join是大表关联小表时的优化选择,是将小表在每一个节点生成相应的Hashtable,这样在关联时就没有Shuffle阶段带来的网络和磁盘IO开销

参数设置:

set hive.auto.convert.join=true
hive.auto.convert.join.noconditionaltask.size=xxx
  • 8. SMB join:
    Sort -Merge -Bucket Join 对大表连接大表的优化,用桶表的概念来进行优化。在一个桶内发送生笛卡尔积连接(需要是两个桶表进行join)

参数设置:

set hive.auto.convert.sortmerge.join=true;  
set hive.optimize.bucketmapjoin = true;  
set hive.optimize.bucketmapjoin.sortedmerge = true;  
set hive.auto.convert.sortmerge.join.noconditionaltask=true;  
  • 9.谓词下推(PPD)
    即谓词下压到最底层,减少数据处理量(默认开启)

参数设置:

set hive.optimize.ppd=true
  • 10.Map端预聚合
    启用Map端聚合可降低数据倾斜情况下带来的影响

参数设置:

set hive.map.aggr=true
  • 11.小文件处理
    小文件的产生有三个地方,map输入,map输出,reduce输出,小文件过多也会影响hive的分析效率

参数设置:

//输入
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
//map 输出
set hive.merge.mapfiles = true
//reduce 输出
set hive.merge.mapredfiles = true
//小文件阈值
set hive.merge.smallfiles.avgsize=xxx
//最终合并文件大小
set hive.merge.size.per.task=256*1024*1024
  • 12.数据倾斜
    表现:任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大

Group by 导致的数据倾斜
当选项设定为true,生成的查询计划会有两个MR Job。当第一个MR Job中,Map的输出结果结合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果。这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的。第二个MR Job再根据预处理的数据结果按照Group By Key分布到reduce中,这个过程可以保证相同的key被分到同一个reduce中,最后完成最终的聚合操作
参数设置:

set hive.groupby.skewindata=true
  • 13.资源配置(内存)
    合理的设置Map 和 Reduce 分配内存大小可以增加计算效率

参数设置:

set mapreduce.map.memory.mb=4096
set mapreduce.reduce.memory.mb=8192

SQL 优化

  • where条件优化
    优化前(关系数据库不用考虑会自动优化):
    select m.cid,u.id from order m join customer u on( m.cid =u.id )where m.dt=‘20180808’;
    优化后(where条件在map端执行而不是在reduce端执行):
    select m.cid,u.id from (select * from order where dt=‘20180818’) m join customer u on( m.cid =u.id);

  • union优化
    尽量不要使用union (union 去掉重复的记录)而是使用 union all 然后在用group by 去重

  • count distinct优化
    尽量不要使用count (distinct cloumn) ,使用子查询

      select count(1) from (select id from tablename group by id) tmp
    
  • 用in 来代替join
    如果需要根据一个表的字段来约束另为一个表,尽量用in来代替join

      select id,name from tb1  a join tb2 b on(a.id = b.id);
      select id,name from tb1 where id in(select id from tb2); in 要比join 快
    
  • 善用explain查看抽象语法树(DAG)

你可能感兴趣的:(Hive,mapreduce,hive)