hive优化基础1

1.hive优化基础1

开启分桶 set hive.enforce.bucketing=true;
设置reduce个数 set mapreduce.job.reduces=3;

  1. hive表 ->orc和parquet -->ZLIB或snappy Parquet是面向分析型业务的列式存储格式

  2. fetch抓取: 在全局找、字段查找、limit查找等都不走mapreduce. set hive.fetch.task.conversion=more;默认为 none.

  3. 本地模式 :
    a. set hive.exec.mode.local.auto=true;
    b. 调节本地模式阈值set hive.exec.mode.local.auto.inputbytes.max=51234560;默认为128M.
    c. 设置local mr的最大输入文件个数 set hive.exec.mode.local.auto.input.files.max=10; 默认 为4.

  4. 大表join小表 map join 优化
    a. set hive.auto.convert.join = true; – 默认为true
    b. 小表阈值设置 : set hive.mapjoin.smalltable.filesize= 25000000; 默认25M.

  5. 大表join 大表 :
    a. 空key过滤
    优化前: SELECT a.* FROM nullidtable a JOIN ori b ON a.id = b.id;
    优化后: SELECT a.* FROM (SELECT * FROM nullidtable WHERE id IS NOT NULL ) a JOIN ori b ON a.id = b.id;
    b. 空key 转换
    有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以表a中key为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的reducer上
    不随机分补:
    SELECT a.*
    FROM nullidtable a
    LEFT JOIN ori b ON CASE WHEN a.id IS NULL THEN ‘hive’ ELSE a.id END = b.id;
    随机分布:
    SELECT a.*
    FROM nullidtable a
    LEFT JOIN ori b ON CASE WHEN a.id IS NULL THEN concat(‘hive’, rand()) ELSE a.id END = b.id;

  6. Sql优化
    1.列裁剪 hive.optimize.cp=true(默认值为真) 只读取查询所需列
    2. 分区裁剪 : 分区参数为:hive.optimize.pruner=true(默认值为真)
    3. group by 当一个key数据过大时数据倾斜.
    (1)是否在Map端进行聚合,默认为True
    set hive.map.aggr = true;
    (2)在Map端进行聚合操作的条目数目
    set hive.groupby.mapaggr.checkinterval = 100000;
    4. Count(distinct) (切记, 数据量小无所谓,数据量大一定不能用)
    由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理
    的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换:

  7. 负载均衡 : 生成两个MR Job计划 , 第一个job 中 第一个MR Job中,
    Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,
    这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的
    第二个MR job 这个过程可以保证相同的Group By Key被分布到同一个Reduce中
    ,最后完成最终的聚合操作
    (3)有数据倾斜的时候进行负载均衡(默认是false)
    set hive.groupby.skewindata = true;

  8. 避免笛卡尔积 (避免join不加on条件或无效条件, hive只能使用1个reduce来完成笛卡尔积)

  9. 动态分区调整
    (1)开启动态分区功能(默认true,开启) set hive.exec.dynamic.partition=true;
    (2)设置为非严格模式动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区
    ,nonstrict模式表示允许所有的分区字段都可以使用动态分区。set hive.exec.dynamic.partition.mode=nonstrict;
    (3)在所有执行MR的节点上,最大可创建多少个动态分区。set hive.exec.max.dynamic.partitions=1000;
    (4)在每个执行MR的节点上,最大可以创建多少个动态分区。
    该参数需要根据实际的数据来设定。set hive.exec.max.dynamic.partitions.pernode=100
    (5)整个MR Job中,最大可以创建多少个HDFS文件。set hive.exec.max.created.files=100000;
    (6)当有空分区生成时,是否抛出异常。一般不需要设置。set hive.error.on.empty.partition=false;

  10. 数据倾斜

    1. 是不是map数越多越好?很多小文件,每个小文件会被当作一个块,用一个map来完成, 而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费
      解决: 减少map数
      set mapred.max.split.size=112345600;
      set mapred.min.split.size.per.node=112345600;
      set mapred.min.split.size.per.rack=112345600;
      三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,
      小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),
      进行合并
      set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
      这个参数表示执行前进行小文件合并,

    是不是保证每个map处理接近128m的文件块,就高枕无忧了?127M,只有两个字段,却有几千万条的记录, 一个map任务去做,很耗时
    解决: 增加map数
    set mapred.reduce.tasks=10; 每个map任务处理大于12M(几百万记录)的数据,效率肯定会好很多
    总结: 控制map数量需要遵循两个原则: 使大数据量利用合适的map数;使单个map任务处理合适的数据量;
    2. reduce个数
    1. Hive自己如何确定reduce数:
    设置每个 reduce 任务处理数据量
    set hive.exec.reducers.bytes.per.reducer=524288000;每个reduce任务处理的数据量 默认1G : 如果源文件总大小为9G多,这次有20个reduce
    每个任务最大的reduce数
    set hive.exec.reducers.max=999 默认999
    计算reducer数的公式 N=min(总输入数据量/参数设置reduce处理数据量)
    a. 那么reduce个数越多越好吗?
    同map一样,启动和初始化reduce也会消耗时间和资源;另外,有多少个reduce,就会有个多少个输出文件,如果生成了很多个小文件,
    那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
    2. 什么情况下只有一个reduce
    很多时候你会发现任务中不管数据量多大,不管你有没有调整reduce个数的参数,
    任务中一直都只有一个reduce任务;其实只有一个reduce任务的情况,除了数据
    量小于hive.exec.reducers.bytes.per.reducer参数值的情况外,还有以下原因:
    没有group by的汇总
    例子: select pt,count(1) from tab_info where pt = ‘2020-07-04’ group by pt;
    select count(1) from tab_info where pt = ‘2020-07-04’;
    用了Order by
    有笛卡尔积。
     注意:在设置reduce个数的时候也需要考虑这两个原则:使大数据量利用合适的reduce数;是单个reduce任务处理合适的数据量;
    11.并行执行
    set hive.exec.parallel=true; --打开任务并行执行
    set hive.exec.parallel.thread.number=16; --同一个sql允许最大并行度,默认为8。
    Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段
    默认情况下,Hive一次只会执行一个阶段。
    不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执
    行的,这样可能使得整个job的执行时间缩短
    不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。

  11. 严格模式
    set hive.mapred.mode = strict; --开启严格模式
    set hive.mapred.mode = nostrict; --开启非严格模式
    开启严格模式可以禁止3种类型的查询。
    1)对于分区表,在where语句中必须含有分区字段作为过滤条件来限制范围,否则不允许执行
    2)对于使用了order by语句的查询,要求必须使用limit语句。
    因为order by为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理
    3)限制笛卡尔积的查询
    13.JVM重用
    JVM重用可以使得JVM实例在同一个job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中进行配置。
    set mapred.job.reuse.jvm.num.tasks=10;手动设置 . 默认公司配好的

  12. 推测执行
    set mapred.map.tasks.speculative.execution=true
    set mapred.reduce.tasks.speculative.execution=true
    set hive.mapred.reduce.tasks.speculative.execution=true;
    推测执行 : 现象:运行程序时,发现有一个程序中的某个Task迟迟不能结束
    解决:如果开启了推测执行,这个task运行过慢,程序会重新启动一个相同的Task,分配到
    机器运行,谁先运行结束,另外一个Task会被终止 可更改配置
    如果用户因为输入数据量很大而需要执行长时间的map或者Reduce task的话,那么启动推测执行造成的浪费是非常巨大大。

猜你喜欢

转载自blog.csdn.net/mitao666/article/details/110470913