Hive 调优相关总结(持续更新)

1)fetch抓取:

  • Hql中的某些查询可以不使用MR计算,例如select * from table;这种情况下Hive可以简单读取table对应的存储目录下的文件
  • 具体的操作方式:在hive/conf/hive-default.xml文件中,修改hive.fetch.task.conversion(minimal和more)为more,这样全局查找,字段查找,filter查找,limit查找等都不走MR,直接Fetch
  • 相关:hive.fetch.task.conversion 之 minimal:执行select * ,limit,filter在一个表所属的分区表上操作,这三种情况都会直接进行数据的拉取,也就是直接把数据从对应的表格拿出来,不用跑mr(范围较 more 小)

2)本地模式:

  • 在单台机器上处理所有的任务。对于小数据集执行时间可以明显被缩短
  • 通过设置hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化

3)表的优化:

  • 3.1)小表 join 大表:
    • key相对分散,并且数据量小的表放在join的左边
    • 多个表关联时,最好分拆成小段,避免大sql(无法控制中间Job);
  • 3.2)大表 join 大表
    • key过滤(异常数据导致的数据倾斜)

    • key转换

  • 3.3)mapjoin
    • 防止全部任务在reducejoin发生的数据倾斜,降低maptask数量
    • 参数:
// 默认为true
set hive.auto.convert.join = true;
  • 3.4)group By
    • Map端聚合,生成两个mr job,保证相同的Group By Key被分布到同一个Reduce
  • 3.5count(distinct) :
    • 数据量大时,一般count distinct使用 先group by count的方式替换
    • eg:

      select  count(distinct ip )  from log_text;  -> select count(ip) from (select ip from log_text group by ip);

  • 3.6)笛卡尔积:
    • 避免join的时候不加on条件,或者无效的on条件

4)使用分区剪裁、列剪裁:

  • 列剪裁:少用select *
  • 分区裁剪:使用分区过滤,关联时先过滤,或直接写成子查询

5)并行模式:

  • 场景:一个 sql 中有多个 job,且 job 间没有依赖关系(表现为 union all)
  • 参数:
// 开启任务并行执行
 set hive.exec.parallel=true;
 // 同一个sql允许并行任务的最大线程数 
set hive.exec.parallel.thread.number=8;

6)严格模式:

  • 严格模式的3中限制:
    • 分区表查询,必用 where (分区字段)来限制范围
    • order by语句查询,要求必须使用limit语句
    • 限制笛卡尔积的查询:必须 join on 连用,不可以 join - where 连用
  • 和动态分区的严格模式区分开:
set hive.exec.dynamic.partition.mode=strict
  • 参数:
<property>

    <name>hive.mapred.mode</name>

    <value>strict</value>

    <description>

      The mode in which the Hive operations are being performed.

      In strict mode, some risky queries are not allowed to run. They include:

        Cartesian Product.

        No partition being picked up for a query.

        Comparing bigints and strings.

        Comparing bigints and doubles.

        Orderby without limit.

    </description>

  </property>

7)JVM 重用:

  • 场景:小文件的场景或者task特别多的场景(jvm 频繁启动造成的开销)
  • job 参数:
//一直占用的 task 插槽数
set mapred.job.reuse.jvm.num.tasks=10;
  • 缺点:一直占用插槽数量(以便重用),所有 task 执行玩之前(“不平衡” job 带来的木桶效应)插槽无法被其他 task 使用

8)推测执行:

  • 推测拖后腿任务,并为之启动备份任务,两任务优先录取
  • 推测执行需要设置Job的两个参数(默认均为true):
 set mapred.map.tasks.speculative.execution = true

 set mapred.reduce.tasks.speculative.execution = true

9)压缩与存储:

  • 9.1)压缩:
    • 压缩指标:
      • 压缩比:压缩比越高,压缩后文件越小,所以压缩比越高越好
      • 压缩时间:越快越好
      • 已经压缩的格式文件是否可以再分割:可以分割的格式允许单一文件由多个Mapper程序处理,可以更好的并行化
    • 各种压缩方式对比:
      • 压缩方式 压缩比 压缩速度 解压缩速度 是否可分割 是否 hadoop 自带
        gzip 13.4% 21 MB/s 118 MB/s
        bzip2 13.2% 2.4MB/s 9.5MB/s
        lzo 20.5% 135 MB/s 410 MB/s 否,要安装
        snappy 22.2% 172 MB/s 409 MB/s 否,要安装
    • hadoop 编/解码器方式 :
      • 压缩格式 对应的编码/解码器
        DEFLATE org.apache.hadoop.io.compress.DefaultCodec
        Gzip org.apache.hadoop.io.compress.GzipCodec
        BZip2 org.apache.hadoop.io.compress.BZip2Codec
        LZO com.hadoop.compress.lzo.LzopCodec
        Snappy org.apache.hadoop.io.compress.SnappyCodec
    • 压缩性能的比较:
      • 压缩算法 原始文件大小 压缩文件大小 压缩速度 解压速度
        gzip 8.3GB 1.8GB 17.5MB/s 58MB/s
        bzip2 8.3GB 1.1GB 2.4MB/s 9.5MB/s
        LZO 8.3GB 2.9GB 49.3MB/s 74.6MB/s
    • 要在Hadoop中启用压缩,可以配置如下参数(mapred-site.xml文件中):
      • 参数 取值 阶段 建议
        io.compression.codecs (在core-site.xml中配置) org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec, org.apache.hadoop.io.compress.Lz4Codec 输入压缩 Hadoop使用文件扩展名判断是否支持某种编解码器
        mapreduce.map.output.compress true mapper输出 这个参数设为true启用压缩
        mapreduce.map.output.compress.codec org.apache.hadoop.io.compress.DefaultCodec mapper输出 使用LZO、LZ4或snappy编解码器在此阶段压缩数据
        mapreduce.output.fileoutputformat.compress true reducer输出 这个参数设为true启用压缩
        mapreduce.output.fileoutputformat.compress.codec org.apache.hadoop.io.compress. DefaultCodec reducer输出 使用标准工具或者编解码器,如gzip和bzip2
        mapreduce.output.fileoutputformat.compress.type NONE|RECORD    
    • 开启Map输出阶段压缩:

      • 开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量

      • 实操:

        • 1)hql语句可能被转换成多个job,如job1的结果作为job2的输入...开启job间结果数据的压缩功能;默认false
          hive (default)>set hive.exec.compress.intermediate=true;
          
          2)开启mapreduce中map输出压缩功能;默认false
          hive (default)>set mapreduce.map.output.compress=true;
          
          3)设置mapreduce中map输出数据的压缩方式;默认DefaultCodec
          hive (default)>set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
          
          4)执行查询语句
          hive (default)>select count(1) from score;
    • 开启Reduce输出阶段压缩:

      • 当Hive将输出写入到表中时,输出内容同样可以进行压缩 

      • 实操:

        • 1)开启hive最终输出数据的压缩功能;默认false
          hive (default)>set hive.exec.compress.output=true;
          
          2)开启mapreduce最终输出数据压缩;默认false
          hive (default)>set mapreduce.output.fileoutputformat.compress=true;
          
          3)设置mapreduce最终数据输出压缩方式;默认DefaultCodec
          hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
          
          4)设置mapreduce最终数据输出压缩为块压缩;默认RECORD
          hive (default)>set mapreduce.output.fileoutputformat.compress.type=BLOCK;
          
          5)测试一下输出结果是否是压缩文件
          insert overwrite local directory '/xxx/install/hivedatas/snappy' 
          select * from score distribute by s_id sort by s_id desc;


注:权威指南第三版说lzo是不可分割的压缩格式,可是我的一张表使用存储rcfile+lzo,在跑hive的时候,产生了很多的map!!!后查阅资料:lzo文件加上index之后可以做分割解压!具体参考:https://blog.csdn.net/liweihope/article/details/89735109

  • 9.2)存储:
    • 常见存储格式:
      • 列存储:ORC, PARQUET
      • 行存储:TEXTFILE, SEQUENCEFILE
    • 尽量使用 orc、parquet 这些列式存储格式,列式存储物理上连续,查询只需要遍历列数据
    • eg:

10)使用 explain(执行计划):

  • explain select * from score where month='201806';

11)数据倾斜:

  • 11.1)合理设置Map数
  • 11.2)小文件合并
  • 11.3)复杂文件增加Map数
  • ​​​​​​​11.4)合理设置Reduce数
     

猜你喜欢

转载自blog.csdn.net/weixin_41346635/article/details/113876207