美文网首页
Hive优化笔记

Hive优化笔记

作者: zhglance | 来源:发表于2021-03-11 21:27 被阅读0次

    1.hive参数优化

    1.1 map个数优化

    map的个数是如何决定的:

    mapred.min.split.size: 数据的最小分割单元大小,默认值是1B
    mapred.max.split.size: 数据的最大分割单元大小,默认值是256MB
    

    一个文件在执行数据处理的时候,被分成文件的个数如下:

    if(一个文件的大小 <= mapred.max.split.size) {
         该文件生成一个map
    } else {
         一个文件的产生的map的个数 = (文件大小 / mapred.max.split.size) + 1
    }
    

    1.1.1 减少map个数:

    set mapred.max.split.size=256000000;  //  -- 决定每个map处理的最大的文件大小 单位为B
    set mapred.min.split.size.per.node=100000000;//每个节点处理的最小split
    set mapred.min.split.size.per.rack=100000000;//每个机架处理的最小slit
    set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;// 默认开启
    
    1.文件大于256MB的进行分割;
    2.那些小于256MB的(包括分割大文件剩下的)进行合并;
    
    

    备注:
    a.四个参数的配置结果大小要满足如下关系。
    max.split.size >= min.split.size >= min.size.per.node >= min.size.per.node

    b.四个参数的作用优先级分别如下
    max.split.size <= min.split.size <= min.size.per.node <= min.size.per.node

    1.1.2 增加map的个数

    a.调节mapred.max.split.size的大小可以达到调整map个数的效果,直接调整mapred.map.tasks这个参数是没有效果的。
    b.拆分文件
    如果一个文件为100MB,属性字段很少,结果数据量却很大(如1000万),使用a方案任然生成一个map,那么可以手动将文件拆分成多个。

    set mapred.reduce.tasks=100;
      create table tableName_1 as 
      select * from tableName t
      distribute by rand(t.name);
    
    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;
    

    1.2 reduce个数优化

    多少个reduce产生多少个输出文件,reduce个数过大会产生过多的小文件,reduce的启动和销毁也会带来消耗;reduce个数过小,单个reduce处理的数据量过大会导致OOM。

    set mapred.reduce.tasks/mapreduce.job.reduces=100
    set hive.exec.reducers.bytes.per.reducer = 256123456// 每个reduce处理的数据量,默认为1GB
    set hive.exec.reducers.max=1009 // 每个任务最大的reduce数,默认为1009
    //如果不设置,hive会根据输入文件估算reduce的个数
    

    2.压缩优化

    hive底层使用mapreduce来实现,而mapreduce的中间过程都需要落入磁盘,消耗大量的网络IO和磁盘IO,因此针对IO密集型job,通过增加CPU资源消耗来降低IO资源的消耗,达到提高性能的目的。

    压缩方式:

    序号 压缩格式 是否可split 是否自带 压缩率 速度 是否Hadoop自带 对应class
    1 gzip 很高 比较快 org.apache.hadoop.io.compress.GzipCodec
    2 lzo 比较高 很快 否,需要安装 org.apache.hadoop.io.compress.LzoCodec
    3 snappy 比较高 很快 否,需要安装 org.apache.hadoop.io.compress.SnappyCodec
    4 bzip2 最高 org.apache.hadoop.io.compress.BZip2Codec

    3.存储优化

    序号 存储格式 行列方式 说明
    1 TextFile 行式存储
    2 Sequence Files 行式存储 支持Block压缩
    3 RCFile 按行分块,按列存储 结合了行存储和列存储的优点
    4 ORCFile 按行分块,按列存储 RCFile的改良版本
    5 parquet 行式存储

    一般选择ORCFile/parquet + snappy 的方式

    4.表结构

    4.1 内部表和外部表

    创建表的时候指定external就是外部表,否则就是内部表。

    序号 表类型 管理方 数据存储位置 元数据 修改表结构
    1 内部表 Hive自身管理 /user/hive/warehouse 内部表删除后元数据和数据都删除 直接同步到元数据
    2 外部表 HDFS管理 用户自己通过location指定 外部表删除后只删除元数据,不删除hdfs数据 需要msck repair table tableName 进行同步到元数据

    4.2 静态分区和动态分区

    静态分区在建表的时候通过PARTITIONED BY定义分区,alter table 添加和删除分区

    动态分区:

    set hive.exec.dynamic.partition=true;
    set hive.exec.dynamic.partition.mode=nonstrict;
    

    4.2 分桶

    分桶通过指定列的数据取hash值将数据进行划分,相同的数据划分到一个桶里,从而减少数据访问量,提高查询效率。

    set hive.enforce.bucketing = true
    CLUSTERED BY (id) INTO 200 BUCKETS  //分桶的列id是表中已有的列
    

    5.sql优化

    5.1 小表放到join左边:

    将数据量小的表或子查询放在join的左边,因为join操作的reduce阶段,将join左边的表的内容加载进内存,因此将数据量小的表放在左边,可以提高效率,一定程度避免OOM。

    5.2 过滤放到关联之前

    列过滤:只select需要的字段
    行过滤:过滤条件放到子查询里

    5.3 开启mapjoin

    set hive.auto.convert.join = true
    set hive.mapjoin.smalltable.filesize=25123456 // 触发mapjoin的小文件大小的阈值
    

    不指定mapjoin开启的情况,hive会把所有join转换为common join,即mapreduce的时候执行join,可以使用mapjoin将小文件的整个数据加载到内存,在map端进行join,避免reduce处理,一定程度上避免了数据倾斜。

    5.4 开启map端聚合

    默认情况下,map阶段同一key数据分发给一个reduce,当一个key数据过大时就倾斜了。不是所有的聚合操作都必须在reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在reduce端得出最终结果。

    set hive.map.aggr = true; // 默认true
     set hive.groupby.mapaggr.checkinterval = 100000; // 在Map端进行聚合操作的条目数目
     set hive.groupby.skewindata = true; // 有数据倾斜的时候进行负载均衡,默认false
    

    5.5 使用先GROUP BY再COUNT的方式替换COUNT DISTINCT

    数据量大的情况下,由于COUNT DISTINCT操作需要用一个reduce task来完成,这一个reduce需要处理的数据量太大,容易产生倾斜问题。

    5.6 查看执行计划

    explain sql // 查看执行计划
    explain extended // 查看详细执行计划
    

    6.其他优化

    6.1 Fetch抓取

    fetch抓取开启一定程度上可以避免触发mapreduce,主要针对全局查找(select *),字段查找(select field),limit(limit 100)等
    开启方式:

    set hive.fetch.task.conversion=more  //关闭:none, 开启(默认):more
    

    6.2 执行模式

    6.2.1 本地模式
    set hive.exec.mode.local.auto=true
    

    主要针对小数据量和测试使用,即在单台机器上处理所有任务,避免在Hadoop集群上启动耗时的问题。

    6.2.2 并行模式
    set hive.exec.parallel=true  //或者通过配置文件来完成,非相互依赖的阶段并行执行,否则默认情况下,Hive一次只会执行一个阶段。
    
    6.2.3 严格模式
    set hive.mapred.mode=strict  // 默认关闭
    

    对于分区表,禁止不指定分区查询
    order by 必须有limit
    禁止笛卡尔积查询

    6.3 JVM重用

    set  mapred.job.reuse.jvm.num.tasks=15;
    

    JVM重用可以使得JVM实例在同一个job中重新使用N次,N值可配置,通常在10~20之间,也可在mapred-site.xml文件中。

    <property>
      <name>mapreduce.job.jvm.numtasks</name>
      <value>15</value> 
    </property>
    

    缺点:JVM不是立即销毁,空闲的时候会导致资源浪费。

    参考资料:

    1.https://my.oschina.net/u/4351661/blog/4268581

    相关文章

      网友评论

          本文标题:Hive优化笔记

          本文链接:https://www.haomeiwen.com/subject/ksioqltx.html