hive优化

 hive优化

hive本质上将sql语句解析成mapreduce程序运行,对于mapreduce的优化同样也会对hive sql的运行起到一定的优化作用,

优化的大致思路大致目标是:增加任务线程来处理、避免数据倾斜

1.增加任务线程来处理

  • 增加reduce数量
    • reduce数量计算公式:N=min(最大的reduce数,总输入数据量/每个reduce的处理数据大小)
      • 每个Reduce处理的数据量默认是256MB,hive.exec.reducers.bytes.per.reducer=256123456
      • 每个任务最大的reduce数,默认为1009 hive.exec.reducers.max=1009
    • 通过group by来增加reduce数量,默认将同一阶段的key发往同一个reduce
      • select col1 [,col2] ,count(1)from table  
        where condition         //Map端执行
        group by col1 [,col2]   //Reduce端执行
        [having]                //Reduce端执行
        例如 select count(distinct s_id) from score是会将数据的全发往一个reduce中,改成select count(1) from (select s_id from score group by s_id),
      • 每个job的Reduce个数可以通过参数mapred.reduce.tasks 指定,输出文件个数与reduce数相同,文件大小与数据量有关
      • order by排序是全局排序,会将数据发到同一个reduce中去,应尽量少用
        • MapReduce内部排序(Sort By) ,对于全局不是排序,单个reduce内部有序
        • 分区排序(DISTRIBUTE BY)结合sort by 一起使用(DISTRIBUTE BY语句要写在SORT BY语句之前。
        • cluster by ;当distribute by和sort by字段相同时 cluster by=distribute by+sort by
  • map数量调整
    • map的数量的计算公式map_num=min(split_num,max(default_num,goal_num)) ;默认 = total_size/block_size; 因为split_size = bloct_size
      • set mapred.map.tasks =10; 只是一个期望值,想增加就这一个比较大的值,
      • split_size=max(mapred.min.split.size,block_size); 实际切片大小
      • mapred.min.split.size是每一个map文件的最小,如果想减少map数量,设置一个比较大的值
      • split_num=total_size/split_size; 切片数量
    • map端聚合
      • set hive.map.aggr = true(默认能在map端聚合的操作会在map端聚合)
    • 例如;原表a只有一个文件,可以先拆分成三个文件,这样每一个map任务只处理三分之一的数据量,效率会提升很多
      • set mapreduce.job.reduces =3;

        create table a_1 as

        select * from a

        distribute by rand(3); 
  • map和reduce的数量不是越多越好,因为启动很好比较慢,对于小文件比较多,应尽量合并小文件
    •  Map最大输入大小:set mapred.max.split.size=256000000;
    • 开启map任务执行前合并小文件:Map前进行小文件合并

2.避免数据倾斜

  • sum,count,max,min等UDAF,不怕数据倾斜问题,hadoop在map端的汇总合并优化,使数据倾斜不成问题。
  • count(distinct )在大数据条件下,效率比较低,
  • 开启优化参数 hive.groupby.skewindata=true 可以开启一优化任务,第一个job会将map输出随机分配到reduce中,实现负载均衡,每一个reduce做部分聚合,第二个job对预处理的结果按照Group By Key分布到Reduce中,完成最总的聚合

 3.表的优化

  • 避免笛卡尔积
  • 分区裁剪: 分区表查询最好带上分区
  • 列裁剪:尽量避免使用select *
  • 动态分区
    • set hive.exec.dynamic.partition = true; 开启动态分区
       set hive.exec.dynamic.partition.mode = nonstrict; 设置为非严格模式,默认strict
      set hive.exec.max.dynamic.partitions = 1000;  所有执行MR的节点上,最大一共可以创建多少个动态分区
      set hive.exec.max.dynamic.partitions.pernode = 100;每个执行MR的节点上,最大可以创建多少个动态分区
      set hive.exec.max.created.files = 100000;   整个Job中,最大可以创建多少个HDFS文件
      set hive.error.on.empty.partition = false;  有空分区生成时,是否抛出异常
    • 注意在SELECT最后几个字段,必须对应前面PARTITION (month,day)中指定的分区字段,包括顺序。
    • 例如 INSERT overwrite TABLE ori_partitioned_target PARTITION (p_time)
      SELECT id, time, uid, keyword, url_rank, click_num, click_url, p_time
      FROM ori_partitioned;

其他参数优化

  • 使用EXPLAIN(执行计划)
    • explain select * from course
    • explain extended select * from course;
  • JVM重用 : Hadoop的默认配置通常是使用派生JVM来执行map和Reduce任务,每个Task运行在一个独立的JVM进程中,JVM重用可以使得JVM实例在同一个job中重新使用N次,减少资源的开启次数
    • 指定重用次数:mapreduce.job.jvm.numtasks 
    •  缺点:开启JVM重用将一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放,如果哪一个task执行时间比其他长,那么保留的插槽就会一直空闲着却无法被其他的job使用
  • 并行执行:有些sql之间是不相关的,可以并行的一起执行
    • 打开任务并行执行:set hive.exec.parallel=true;
    • 同一个sql允许最大并行度:set hive.exec.parallel.thread.number=16;  //默认为8。
  • 尽量避免使用mr
    • 将hive-default.xml.template文件中hive.fetch.task.conversion设置为more(默认也是more),这样在全局查找和指端查找,limit查找不会走mapreduce,例如select * from score; select s_score from score; select s_score from score limit 3;
  • 关闭推测执行:如果没有关闭,那么当一个任务执行时间很长时,程序会认为程序卡了,再开一个任务来执行
    • mapred.reduce.tasks.speculative.execution
    • hive.mapred.reduce.tasks.speculative.execution 

       

        
        

          
 

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值