从小就学习不好

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

首先hive本质就是mapreduce,那么优化就从mapreduce开始入手。

然而mapreduce的执行快慢又和map和reduce的个数有关,所以我们先从这里下手,调整并发度。

关于map的优化:

  1.调整block

    作业会通过input的目录产生一个或者多个map任务。set dfs.block.size

    因为没份数据都是block,而block的大小直接影响了split切分的分数,如果切分的更细一点,那么split个数会增加,那直接会影响map的增加,所以blocksize是直接影响并发度的因素

    通过该配置参数来调整map个数:

      set mapred.max.split.size=100000000;

      set mapred.min.split.size.per.node=100000000;

      set mapred.min.split.size.per.rack=100000000; 

      set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

    还可以直接设置map个数:

      set mapred.map.tasks=10;

      注:这种方式进行设置,并不一定会生效

    开启combiners

      Map端聚合 hive.map.aggr=true

      注:用的好了,可以提高性能,用的不好了,反而影响结果(可以参考mapreduce的combiner)

关于reduce的优化:

  hive.exec.reducers.bytes.per.reducer;reduce任务处理的数据量

    这个参数可以在提交sql的时候设置这个参数,这个参数可以直接设置一个数字,这个数字会直接影响reduce的个数

    reduce个数的计算公式(hive.exec.reducers.bytes.per.reducer):

      reduce个数 = InputFileSize  / bytes pre reduce(整个数据的大小 / 每一个reduce可以处理的大小)

      hive.exec.reducers.bytes.per.reducer这个参数设置的就是每个reduce可以处理的大小

   set mapred.reduce.tasks=10(也是设置reduce的个数)

    如果hive.exec.reducers.bytes.per.reducer和set mapred.reduce.tasks同时设置了,set mapred.reduce.tasks 优先级高

---------------------------------------------------------------------------------------------------------------------------------------------------------------

  例如:1)查询count这种聚合函数,如果使用的group by的话会多个reduce来运行,而没有使用group by的话就是单个reduce来运行,所以面对大量数据做聚合,使用group by

     where pt=‘20190308’ 单个reduce运行 (bed case)

     where pt=‘20190308’ group by pt 多个reduce运行 (good case)

 

     2)两张表做join的时候,使用on是多个reduce来运行,而不使用on则是一个reduce来运行(两张表做join,一定要用on

     select id,xxx from table_A  A join table_B B on A.id=B.id  多个reduce运行 (good case)

     select id,xxx from table_A A join table_B B where A.id=B.id 单个reduce运行  (bed case)

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

partition做分区,直接定位到分区,省去一些不必要的过滤

  分区的问题看上一篇博客

Map Join:类似一种检索配置的形式

    /*+ MAPJOIN(tablelist) */,必须是小表,不要超过1G,或者50万条记录

    有A,B两张表,A想joinB     A.join(B)

    如果A是小表,B是大表,可以将A放入内存(小表有多小?尽量不要超过1G)

Union操作:合并去重操作

    table_A: A,B,C    table_B:B,C,D   Union:A,B,C,D

Union all操作:直接追加不做去重

    table_A: A,B,C    table_B:B,C,D   Union:A,B,C,B,C,D

    Union all不去重,性能明显高于Union

    先做union all再做join或group by等操作可以有效减少mapreduce过程,尽管是多个Select,最终只有一个mapreduce

    明确数据不相同或者有相同不需要去重就用Union all,有相同就用Union

Automatic merge:

  执行hive的过程中,中间可能产生一些小文件,在中间做一些文件的合并

    – hive.merge.mapfiles = true 是否和并 Map 输出文件,默认为 True

    – hive.merge.mapredfiles = false 是否合并 Reduce 输出文件,默认为 False

    – hive.merge.size.per.task = 256*1000*1000 合并文件的大小

Multi-Count Distinct:  

  当我们写一个sql的时候

    sql(group by key)------>一个MR job

    map相同的key------->同一个reduce

    假设数据源存在数据倾斜问题

    所有的reduce都完成了,最后等1个reduce

    怎么优化?(mapreduce中:对key改写来解决此类问题)

    hive中:set hive.groupby.skewindata=true  (会自动的帮你完成负载均衡)

--------------------------------------------------------------------------------------------------------

在mapreduce中,什么时候会耗时比较严重呢?

  在做join的时候会耗时比较严重

  hive是可以支持多表链接的

    一个mapreduce的例子:

      select a.val, b.val, c.val from a join b on(a.key = b.key1) join c on(a.key = c.key1)  一个MR job(good case)

      select a.val, b.val, c.val from a join b on(a.key = b.key1) join c on(b.key2 = c.key)  多个MR job (bad case)

    如果join多张表,join的key是同一个的时候,会生成一MR job

  

Hive的 Join 优 化 — — 表连接顺序  

  hive会默认把左边的数据放入内存,右边的数据做类似流数据(最好每次写join的是,小标放左边,大表放右边

  A.join(B)

  reducer会尝试把A表进行缓存,因为A在前面B在后面(它会把最后一张表前的所有表都尝试进行缓存)如果A完全可以放入内存中去,对B进行遍历,进行join,如果B有n条记录,那它的时间复杂度就是O(n)

     如果A,B都不在内存中,A的大小是m,B的大小是n,那它的时间复杂度就是O(m*n)

   当大小表的顺序有问题,又不想改写顺序:

    SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM a  JOIN b ON (a.key = b.key1)  JOIN c ON (c.key = b.key1);     a表被视为大表

    SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM a JOIN b ON a.key = b.key;      MAPJION会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多

-------------------

  左连接时,左表中出现的JOIN字段都保留,右表没有连接上的都为空。

  SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key) WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'

      执行顺序是,首先完成2表JOIN,然后再通过WHERE条件进行过滤,这样在JOIN过程中可能会输出大量结果,再对这些结果进行过滤,比较耗时。

    SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key AND a.ds='2009-07-07' AND b.ds='2009-07-07')

      可以进行优化,将WHERE条件放在ON后,在JOIN的过程中,就对不满足条件的记录进行了预先过滤。

Hive的优化 — — 并行执行

  同步执行hive的多个阶段,hive在执行过程,将一个查询转化成一个或者多个阶段。某个特定的job可能包含众多的阶段,而这些阶段可能并非完全相互依赖的,也就是说可以并行执行的,这样可能使得整个job的执行时间缩短。

  hive执行开启:set hive.exec.parallel=true

    

数据倾斜:

  我们优化大部分的目标都是为了解决数据倾斜的问题  

  • 操作

    • Join
    • Group by
    • Count Distinct  

  • 原因
    • key分布不均导致的
    • 人为的建表疏忽
    • 业务数据特点

  • 症状

    • 任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成

    • 查看未完成的子任务,可以看到本地读写数据量积累非常大,通常超过10GB可以认定为发生数据倾斜

  • 倾斜度

    • 平均记录数超过50w且最大记录数是超过平均记录数的4倍

    • 最长时长比平均时长超过4分钟,且最大时长超过平均时长的2倍

  • 万能方法

    • hive.groupby.skewindata=true

Hive的优化 ------数据倾斜------大小表关联

  • 原因

    • Hive在进行join时,按照join的key进行分发,而在join左边的表的数据会首先读入内存

      如果左边表的key相对分散,读入内存的数据会比较小,join任务执行会比较快;

      如果左边的表key比较集中,而这张表的数据量很大,那么数据倾斜就会比较严重;

  • 思路

    • 将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率

    • 使用map join让小的维度表先进内存

  • 方法

    • Small_table join big_table

      

Hive的优化 ------数据倾斜------大大表关联

  • 原因

    • 日志中有一部分的userid是空或者是0的情况,导致在用user_id进行hash分桶的时候,会将日志中userid为0或者空的数据分到一起,导致了过大的斜率

  • 思路

    • 把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果

  

Hive的优化 ------数据倾斜------聚合时存在大量特殊值

  • 原因

    • 做count distinct时,该字段存在大量值为NULL或空的记录

  • 思路

    • count distinct时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1

    • 如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union

  • 方法

    • select cast(count(distinct(user_id))+1 as bigint) as user_cnt from tab_a where user_id is not null and user_id <> ‘ ‘

 

posted on 2019-03-08 17:27  从小就学习不好  阅读(444)  评论(0编辑  收藏  举报