7、Hive 优化

-  hdfs作为存储层
-  MapReduce作为计算层

sql->mr
--查看执行计划,添加extended关键字可以查看更加详细的执行计划
explain [extended] query
1、抽象语法树
2、查询块
3、逻辑查询计划
4、物理查询计划
5、优化执行

 

执行模式
1、本地模式(开发,速度会有所提升):
  set hive.exec.mode.local.auto=true;  默认false
  --设置读取数据量的大小限制,超出使用集群模式
  set hive.exec.mode.local.auto.inputbytes.max=128M  设计到的文件不能超过4个文件

2、并行模式
  在SQL语句足够复杂的情况下,可能在一个SQL语句中包含多个子查询语句,且多个子查询语句之间没有任何依赖关系,此时,可以Hive运行的并行度
  set hive.exec.parallel=true;
  set hive.exec.parallel.thread.number=83、严格模式:充分利用Hive的某些特点
  set hive.mapred.mode=strict;
    注意:当设置严格模式之后,会有如下限制:
  (1)对于分区表,必须添加where对于分区字段的条件过滤
2)order by语句必须包含limit输出限制 (3)限制执行笛卡尔积的查询

 

 

抓取策略
默认所有SQL都回转成MapReduce-----more
对某些情况的查询不需要使用MapReduce计算
set hive.fetch.task.conversion=none/more;

 

排序
1、Order By - 对于查询结果做全排序,只允许有一个reduce处理
    (当数据量较大时,应慎用。严格模式下,必须结合limit来使用)
2、Sort By - 对于单个reduce的数据进行排序
3、Distribute By - 分区排序,经常和Sort By结合使用          ;     可以指定升序还是降序
4、Cluster By - 相当于 Sort By + Distribute By      同一个字段
    (Cluster By不能通过asc、desc的方式指定排序规则;
        可通过 distribute by column sort by column asc|desc 的方式)

 

JOIN

1、Map Join:在Map端完成Join
    两种实现方式:
        -    SQL方式:在SQL语句中添加MapJoin标记(mapjoin hint),小表会先被加载到内存中
                   语法:
            select /*+MAPJOIN(smallTable)*/ smallTable.key, bigTable.value
            FROM smallTable JOIN bigTable ON smallTable.key = bigTable.Key; - 开启自动地MapJoin
        set hive.auto.convert.join=true; 会优先对左边的小表进行加载
        
        hive.mapjoin.amslltable.filesize; 大小表阈值判断 (25000000 ≈·25MB )
        hive.ignore.mapjoin.hint  默认true(当同时开启自动mapjoin、声明mapjoin);采取哪一种。 true 采取自动
        
2、Hive join  :尽可能使用相同的连接键(会转化为一个MapReduce作业)
3、大表join大表
  -  空key过滤:有时join超时是因为某些key对应的数据太多,而相同的key对应的数据都回发送到相同的reducer上,从而导致内存不够。此时我们应该分析这些异常            的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤
  -  空key转换:有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以再表a中key为空的字段赋一个随机的            值,使得数据随机均匀地分布到不同的reducer上
 Map-Side聚合
set hive.map.agger=true;  开启聚合
目的: 综合考虑与reduce端shuffle 的效率

hive.groupby.mapagger.checkinterval;
    map端group by 执行局和时处理的多少行数据,默认100000


hive.map.aggr.hash.min.reduction;
    进行聚合最小比例 (预先对100000条数据做聚合,若聚合后的数据量/100000大于该配置的0.5,则不会聚合)

hive.map.aggr.hash.percentmemory;
    聚合使用的内存最大值

hive.groupby.skewindata
    是否对groupby产生的数据倾斜做优化,默认为false
合并小文件
-    文件小,容易在文件存储端造成压力,给hdfs造成压力,影响效率
-    设置合并属性
    是否合并map端输出文件    hive.merge.mapfiles =true
    是否合并reduce端输出文件    hive.merge.mapredfiles =true
    合并文件的大小    hive.merge.size.per.task=256*1000*1000
去重统计
数据量小的时候,无所谓

数据量大时,由于COUNT DISTINCT 操作需要用一个Reduce Task来完成,这是一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般count distinct 会使用先group by 再 Count的方式替换
Map和Reduce的数量
map:
  mapred.max.split.size       每个map处理文件的最大值
  mapred.min.split.size.per.node     节点上split的最小值
  mapred.min.split.size.per.rack      一个机架上split的最小值
      
    数量由block数量控制



reducer
   mapred.reduce.tasks    强制指定reduce的任务数量
    hive.exec.reducers.bytes.per.reducer     每个任务处理的数据量
    hive.exec.reducers.max     每个任务最大的reduce数
JVM重用
使用场景(连接池):
    -    小文件个数过多
    -    task个数过多

set mapred.job.reuse.jvm.num.tasks=n 来设置
   

缺点:
设置开启后,task插槽会一直占用资源,不论是否有task运行,知道所有的task即 整个job全部执行完毕时,才会释放所有的task插槽资源 

 

 

 

 

压缩

配置
支持 的压缩编码


| 压缩格式 | 工具  | 算法    | 文件扩展名 | 是否可切分 |
| -------- | ----- | ------- | ---------- | ---------- |
| DEFAULT  | 无    | DEFAULT | .deflate   | 否         |
| Gzip     | gzip  | DEFAULT | .gz        | 否         |
| bzip2    | bzip2 | bzip2   | .bz2       | 是         |
| LZO      | lzop  | LZO     | .lzo       | 否         |
| LZ4      | 无    | LZ4     | .lz4       | 否         |
| Snappy   | 无    | Snappy  | .snappy    | 否         |

为了支持多种压缩/解压缩算法,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.compression.lzo.LzopCodec       |
| LZ4      | org.apache.hadoop.io.compress.Lz4Codec     |
| Snappy   | org.apache.hadoop.io.compress.SnappyCodec  |

 

压缩配置参数
要在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                     | false                                                        | mapper输出  | 这个参数设为true启用压缩                     |
| mapreduce.map.output.compress.codec               | org.apache.hadoop.io.compress.DefaultCodec                   | mapper输出  | 使用LZO、LZ4或snappy编解码器在此阶段压缩数据 |
| mapreduce.output.fileoutputformat.compress        | false                                                        | reducer输出 | 这个参数设为true启用压缩                     |
| mapreduce.output.fileoutputformat.compress.codec  | org.apache.hadoop.io.compress. DefaultCodec                  | reducer输出 | 使用标准工具或者编解码器,如gzip和bzip2      |
| mapreduce.output.fileoutputformat.compress.type   | RECORD                                                       | reducer输出 | SequenceFile输出使用的压缩类型:NONE和BLOCK  |

 

开启Map输出压缩
目的:减少map和reduce之间数据传输量


--1)开启hive中间传输数据压缩功能
    hive (default)>set hive.exec.compress.intermediate=true;
--2)开启mapreduce中map输出压缩功能
    hive (default)>set mapreduce.map.output.compress=true;
--3)设置mapreduce中map输出数据的压缩方式
    hive (default)>set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;

--4)执行查询语句
hive (default)> select count(*) from aaaa;
开启Reduce输出阶段压缩
当Hive将输出写入到表中时,输出内容同样可以进行压缩。

--1)开启hive最终输出数据压缩功能
    hive (default)>set hive.exec.compress.output=true;
--2)开启mapreduce最终输出数据压缩
    hive (default)>set mapreduce.output.fileoutputformat.compress=true;
--3)设置mapreduce最终数据输出压缩方式
    hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
--4)设置mapreduce最终数据输出压缩为块压缩
    hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;
--5)测试一下输出结果是否是压缩文件
    hive (default)> insert overwrite local directory '/root/data' select * from aaaa;
文件存储格式
Hive支持的存储数的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET。

TEXTFILESEQUENCEFILE的存储格式都是基于行存储的;
ORCPARQUET是基于列式存储的。      (历史数据,不适用于插入数据);    省空间,但查询有所影响

列式存储可以针对性的设计更好的设计压缩算法
时间
text:0.156
orc :0.127
par :0.17
压缩比: ORC>Parquet>text

-  TEXTFILE
  默认格式,数据不压缩,磁盘开销大,数据解析开销大,可结合Gzip,Bzip2使用(系统自动检查,执行查询时自动解压
  hive不会对数据进行切分,从而无法对数据进行并行操作。
-  Orc
  

   默认采用ZLIB压缩

  可以看到每个Orc文件由1个或多个stripe组成,每个stripe 250MB大小,这个Stripe相当于RowGroup,不过大小由4MB->250MB


  这样应该能提升顺序读的吞吐率。 每个stripe里有三部分组成,分别是


    -  Index  轻量级索引,每隔1W行做一个索引,只记录每行的个字段在Row Data中的offset


    -  Row   存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个Stream来存储


    -  Stripe  存储的是各个Stream的类型,长度等信息


    -  File Footer 存的是每个Stripe的行数,每个Column的数据类型信息等;每个文件的尾部是一个PostScript,记录了


               整个文件的压缩类型以及FileFooter的长度信息等。在读取文件时,会seek到文件的尾部,从中解析File


              Footer长度,在读取,从里面解析到各个stripe信息,在读各个stripe,即从后往前读


-  PARQUET 

 


 

Parquet是面向分析型业务的列式存储格式 
Parquet文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的数据和元数据,因此Parquet格式文件是自解析的。
通常情况下,在存储Parquet数据的时候会按照Block大小设置行组的大小,由于一般情况下每一个Mapper任务处理数据的最小单位是一个Block,
这样可以把每一个行组由一个Mapper任务处理,增大任务执行并行度。Parquet文件的格式如下图所示。

   

 

ORC存储方式的压缩

 

官网:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC
CREATE EXTERNAL TABLE psn   
(
id int,
name string,
likes ARRAY<string>,
address ARRAY<string>
)
PARTITIONED BY (gender string)    
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '-'
MAP KEYS TERMINATED BY ':'
stored as orc 
LOCATION '/data'
tblproperties ("orc.compress"="NONE");
| Key                      | Default    | Notes                                                        |
| ------------------------ | ---------- | ------------------------------------------------------------ |
| orc.compress             | ZLIB       | high level compression (one of NONE, ZLIB, SNAPPY)           |
| orc.compress.size        | 262,144    | number of bytes in each compression chunk                    |
| orc.stripe.size          | 67,108,864 | number of bytes in each stripe                               |
| orc.row.index.stride     | 10,000     | number of rows between index entries (must be >= 1000)       |
| orc.create.index         | true       | whether to create row indexes                                |
| orc.bloom.filter.columns | ""         | comma separated list of column names for which bloom filter should be created |
| orc.bloom.filter.fpp     | 0.05       | false positive probability for bloom filter (must >0.0 and <1.0) |

 

 

HIVE高可用

 

posted @ 2020-07-05 11:41  慕沁  阅读(159)  评论(0)    收藏  举报