Hive调优与数据倾斜优化

一、Hive调优策略

  • 架构调优
    1、执行引擎:Hive默认使用的是MR,可以换为Tez,Tez将多个mapReduce任务合并成一个较大的DAG任务,减少mapreduce迭代过程中文件存储,其他的引擎可以是spark,flink等;
    2、分区分桶表:对于一张较大的表,将其设计成分区表可以提高查询性能,一般是日期;分桶表的组织方式是将HDFS上的文件分割成多个文件,分桶表可以加快数据的抽样,提升JOIN的性能;
    3、文件存储格式:Hive默认使用TextFile,可以指定为SequenceFile,Parquet,ORC等格式;其中Parquet等列式存储需要TextFile作为跳板;
    4、文件压缩格式:减少map和reduce之间的数据传输,从而可以提升查询性能
    --开启压缩
    SET hive.exec.compress.intermediate=true
    -- 中间结果压缩
    SET hive.intermediate.compression.codec=org.apache.hadoop.io.compress .SnappyCodec
    -- 输出结果压缩
    SET hive.exec.compress.output=true;
    SET mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodc
  • 参数调优
    1、使用本地模式:当Hive处理小数据量时,启动分布式查询会浪费时间,Hive支持将作业转为本地模式,需要开启一下配置
    SET hive.exec.mode.local.auto=true

    2、严格模式:主要包含三种类型的SQL,一旦执行将报错,分别是查询分区表时不限定分区列的语句;两表JOIN产生笛卡尔积的语句;使用order by排序时没有limit语句

    SET hive.mapred.mode=nostrict

    3、JVM重用:默认情况下hadoop会为每一个map task和reduce task启动一个JVM,这样可以并行执行任务。当某个task是轻量级的作业时,JVM的启动要比作业的执行时间还要长。此时hadoop可以重用JVM,通过共享JVM以串行的方式运行task;当然存在不好的地方是,启动的JVM会一直占用task插槽,直到任务运行结束才释放,比如存在不平衡的job,少数几个map或者reduce task执行时间长的话该JVM会空闲。

    SET mapreduce.job.jvm.numtasks=4

    4、合并小文件

    --在map task执行前合并小文件
    set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFo rmat;

    --在reduce结束时合并小文件
    SET hive.merge.mapfiles = true;
    SET hive.merge.mapredfiles = true;
    SET hive.merge.size.per.task = 268435456;
    SET hive.merge.smallfiles.avgsize = 16777216;

    5、Fetch模式:Hive中对于某些查询不必使用MapReduce计算,可以简单的读取对应的存储文件,输出结果, hive.fetch.task.conversion=more

  • SQL调优
    1、列裁剪和分区裁剪
    2、sort by代替order by
    3、group by代替count(distinct col)
    4、处理空值与无意义的值
    5、单独处理热KEY
    6、JOIN优化
    7、GROUP BY配置调整
    --map端预聚合:即在map端启动一个combiner做预聚合,减少shuffle的数据量,减少io传输
    set hive.map.aggr=true

    --倾斜均衡配置项:group by时某些key的数据量过大,会发生数据倾斜; 原理为启动两个MR,第一个job将map的数据随机写入reducer,做部分聚合,第二个job在进行聚合
    set hive.group.skewindata=true
    8、合理的设置map数和reduce数
      map数处理:map数量主要和输入文件总数,输入文件大小,hdfs文件快大小;map数量并不是越多越好,一个任务有很多小文件,每个文件会启动一个map任务,会造成资源浪费;当一个文件接近128M时,假设它字段很少,但行数很多,但其处理逻辑比较复杂,使用就一个map去做,性能也不会很好;
      reduce数处理:可以设置set mapred.reduce.tasks=n,不设置会自动下推,当然reduce也不是越多越好,reduce太多,生成的小文件越多,对hdfs造成压力;reduce数量太少,每个reduce要处理很多数据,容易拖慢运行时间或者造成OOM

二、数据倾斜出现场景以及解决

  总的来说,出现数据倾斜主要两个原因:一是任务中需要处理大量相同的key的数据;二是任务读取不可分割的大文件;一个发生在reduce中,一个发生在map中,map中一般由于文件不可切分,Gzip格式的
  • 空值引发的数据倾斜
    有时业务数据存在大量的null值或者无意义的值,在JOIN中,所有的null值将分配到一个reduce中,必然产生数据倾斜
    --过滤null值,不参与处理逻辑
    if(col is null, concat('rand_', rand()))

    --join
    select * from a left join b on case when a.col_name is null then concat('rand_', rand()) else a.col_name end = b.col_name
  • 不同数据类型产生的数据倾斜
  • 数据膨胀引发的数据倾斜
  • 不可拆分大文件引发数据倾斜
  • 表连接时发生的数据倾斜:1)大表join小表:map join,需要关注小表数据量  2)裁剪,二次聚合,热key分离,key值采样
  • GROUP BY 引发的数据倾斜
  • SQL语句自身存在的数据倾斜:collect_set,调整reduce的内存大小

 

posted @ 2021-11-22 15:46  Shydow  阅读(457)  评论(0编辑  收藏  举报