hive 参数优化记录

HDFS非常容易存储大数据文件,如果Hive中存在过多的小文件会给namecode带来巨大的性能压力。同时小文件过多会影响JOB的执行,hadoop会将一个job转换成多个task,即使对于每个小文件也需要一个task去单独处理,task作为一个独立的jvm实例,其开启和停止的开销可能会大大超过实际的任务处理时间。
  同时我们知道hive输出最终是mr的输出,即reducer(或mapper)的输出,有多少个reducer(mapper)输出就会生成多少个输出文件,根据shuffle/sort的原理,每个文件按照某个值进行shuffle后的结果。
  为了防止生成过多小文件,hive可以通过配置参数在mr过程中合并小文件。而且在执行sql之前将小文件都进行Merge,也会提高程序的性能。我们可以从两个方面进行优化,其一是map执行之前将小文件进行合并会提高性能,其二是输出的时候进行合并压缩,减少IO压力。

一、hive参数优化


Map操作之前合并小文件:

#每个Map最大输入大小设置为2GB(单位:字节)
set mapred.max.split.size=2147483648
 
set hive.hadoop.supports.splittable.combineinputformat=true;
#执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
输出时进行合并:

#在Map-only的任务结束时合并小文件。是否和并 Map输出文件,默认为 True,
set hive.merge.mapfiles = true
 
#在Map-Reduce的任务结束时合并小文件
set hive.merge.mapredfiles= true
 
#合并后MR输出文件的大小为1GB
set hive.merge.size.per.task = 1073741824
 
#当输出文件的平均大小小于1GB时,启动一个独立的map-reduce任务进行文件merge
set hive.merge.smallfiles.avgsize=1073741824
 
 
二、文件压缩

set hive.exec.compress.output=true;
#默认false,是否对输出结果压缩

set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
#具体的压缩算法的配置参数,要使用的压缩编码/解码器的类名。

set mapred.output.compression.type=BLOCK;
sequencefile有三种压缩方式:NONE, RECORD, BLOCK。默认是启用RECORD级(压缩单独的记录)的压缩的,这种方式的压缩率是非常低的。BLOCK(压缩一组记录)压缩率最高,一般用BLOCK。

set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
SnappyCodec比较适合在这种场景中编解码器,该算法会带来很好的压缩性能和较低的CPU开销
 

1、Hive中间数据压缩Lzo,最终数据压缩Gzip

set mapred.compress.map.output = true;  
set mapred.map.output.compression.codec = org.apache.hadoop.io.compress.LzoCodec; 
 
set mapred.output.compress = true;  
set mapred.output.compression.codec = org.apache.hadoop.io.compress.GzipCodec;  
set mapred.output.compression.type = BLOCK;  
  
set hive.exec.compress.intermediate = true;   #启用中间数据压缩
set hive.intermediate.compression.codec = org.apache.hadoop.io.compress.LzoCodec;  
set hive.exec.compress.output = true;  
三、文件存储

hive在创建表时默认存储格式是textfile,或者显示自定义的stored as textfile.hive常用的存储格式有三种,textfile,sequencefile,rcfile。
为什么hive会有多种存储格式?因为hive是文本批处理系统,所以就存在一个往hive中导入数据的问题,首先数据的存储格式有多种,比如数据源是二进制格式, 普通文本格式等等,而hive强大之处不要求数据转换成特定的格式,而是利用hadoop本身InputFormat API来从不同的数据源读取数据,同样地使用OutputFormat API将数据写成不同的格式。所以对于不同的数据源,或者写出不同的格式就需要不同的对应的InputFormat和Outputformat类的实现。

以stored as textfile(其实这就是下面stored as inputformat -outputformat的缩减写法)为例,其在底层java API中表现是输入InputFormat格式:TextInputFormat以及输出OutputFormat格式:HiveIgnoreKeyTextOutputFormat.这里InputFormat中定义了如何对数据源文本进行读取划分,以及如何将切片分割成记录存入表中。而Outputformat定义了如何将这些切片写回到文件里或者直接在控制台输出。

  STORED AS INPUTFORMAT 
           'org.apache.hadoop.mapred.TextInputFormat' 
  OUTPUTFORMAT 
          'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
实际上hive使用一个TextInputFormat对象将输入流分割成记录,然后使用一个HiveIgnoreKeyTextOutputFormat对象来将记录格式化为输出流(比如查询的结果),再使用Serde在读数据时将记录解析成列。在写数据时将列编码成记录。所以stored as ''只是决定了行级别(记录级别 )的存储格式,而实际将记录解析成列依靠的则是Serde对象,比如hive默认的ROW FORMAT SERDE   'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'  。或者用户自定义的Serde格式。

textfile,sequencefile和rcfile的三种存储格式的本质和区别

     文件存储编码格式    建表时如何指定    优点弊端
textfile         
文件存储就是正常的文本格式,将表中的数据在hdfs上 以文本的格式存储

,下载后可以直接查看,也可以使用cat命令查看

1.无需指定,默认就是

2.显示指定stored as textfile

3.显示指定 

STORED AS INPUTFORMAT 

   'org.apache.hadoop.mapred.TextInputFormat' 

  OUTPUTFORMAT           'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

1.行存储使用textfile存储文件默认每一行就是一条记录,

2.可以使用任意的分隔符进行分割。

3.但无压缩,所以造成存储空间大。可结合Gzip、Bzip2、Snappy等使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。

4、 textfile为默认格式,存储方式为行存储

sequencefile       
在hdfs上将表中的数据以二进制格式编码,并且将数据压缩了,下载数据

以后是二进制格式,不可以直接查看,无法可视化。

1.stored as sequecefile

2.或者显示指定:

STORED AS INPUTFORMAT 

  'org.apache.hadoop.mapred.SequenceFileInputFormat' 

OUTPUTFORMAT 

 'org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat'

1.sequencefile存储格有压缩,存储空间小,有利于优化磁盘和I/O性能

2.同时支持文件切割分片,提供了三种压缩方式:none,record,block(块级别压缩效率跟高).默认是record(记录)

3.基于行存储

rcfile       在hdfs上将表中的数据以二进制格式编码,并且支持压缩。下载后的数据不可以直接可视化。    
1.stored as rcfile 

2.或者显示指定:

STORED AS INPUTFORMAT 

  'org.apache.hadoop.hive.ql.io.RCFileInputFormat' 

OUTPUTFORMAT 

  'org.apache.hadoop.hive.ql.io.RCFileOutputFormat'

1.行列混合的存储格式,基于列存储。

2.因为基于列存储,列值重复多,所以压缩效率高。

3.磁盘存储空间小,io小。

4.hive/spark都支持这种存储格式,它存储的方式是采用数据按照行分块,每个块按照列存储,其中每个块都存储有一个索引。特点是数据压缩率非常高。

创建时可以直接指定存储格式

create table parquet(
...
)
row format delimited fields terminated by '\t'
stored as parquet;
hive中不同存储格式转换,需要使用insert ....select

磁盘空间占用大小比较(较大数据量)
orc<parquet<textfile

四、行列分隔符

CREATE TABLE `dwa_mytable`(
  `msisdn` string COMMENT '手机号码', 
  `location` string COMMENT '位置'
   )
PARTITIONED BY ( 
  `month_id` string, 
  `day_id` string, 
  `prov_id` string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' 
WITH SERDEPROPERTIES ( 
  'field.delim'='|', 
  'serialization.format'='|') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://beh/user/hadoopvip/lf_xx_dwa.db/dwa_mytable'
TBLPROPERTIES (
  'last_modified_by'='hadoopvip', 
  'last_modified_time'='1524300660', 
  'transient_lastDdlTime'='1524300600')
Time taken: 0.062 seconds, Fetched: 49 row(s)
hive默认的列分割类型为org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe,而这其实就是^A分隔符,hive中默认使用^A(ctrl+A)作为列分割符,如果用户需要指定的话,等同于row format delimited fields terminated by '\001',因为^A八进制编码体现为'\001'.所以如果使用默认的分隔符,可以什么都不加,也可以按照上面的指定加‘\001’为列分隔符,效果一样。

hive默认使用的行分隔符是'\n'分隔符 ,也可以加一句:LINES TERMINATED BY '\n' ,加不加效果一样。但是区别是hive可以通过row format delimited fields terminated by '\t'这个语句来指定不同的分隔符,但是hive不能够通过LINES TERMINATED BY '$$'来指定行分隔符,目前为止,hive的默认行分隔符仅支持‘\n’字符。否则报错。

hive ()>  create table  fdm_sor.mytest_tm4(
              >   id int comment'编号',
              >  name string comment '名字'
              >  )
              >  lines terminated by '\t';
FAILED: ParseException line 5:1 missing EOF at 'lines' near ')';

猜你喜欢

转载自blog.csdn.net/maenlai0086/article/details/90606074