• 关于hive的优化


    首先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 <> ‘ ‘

  • 相关阅读:
    Python 30分钟入门——数据类型 &amp; 控制结构
    POJ 3101 Astronomy
    Java8 Lamdba表达式 001
    浅谈PPM (Project Portfolio Management)
    char* 和char[]的差别
    福州大学第十一届程序设计竞赛
    用 Python 测试框架简化测试
    15个最受欢迎的Python开源框架
    python测试框架总结
    python测试框架--nose
  • 原文地址:https://www.cnblogs.com/fishperson/p/10497113.html
Copyright © 2020-2023  润新知