7.其他文件格式和压缩方法

  • Hive不会强制要求数据转换成特定的格式才能使用,Hive利用Hadoop的InputFormat API来从不同的数据源读取数据,例如文本格式,sequence文件格式以及parquet、avro等等格式。

确定编解码器

  • 通过io.compression.codec可以看到编解码器之间是按照逗号进行分隔的。

选择压缩编/解码器

  • 使用压缩的优势是可以最小化所需要的磁盘存储空间,以及减少网络和网络IO操作,不过文件压缩过程和解压过程需要消耗CPU开销,因此对于CPU密集型的job最好不要使用压缩。

  • 压缩方案选择

    • BZip2压缩率最高,但是需要消耗更多的cpu资源

    • GZip是压缩率和压缩/解压速度上的一个选择。不可分割

    • LZO/Snappy(不可分割)压缩率比前两种低,但是压缩/解压缩速度快,特别是解压缩,如果对于磁盘空间和io开销,频繁读取数据所需的解压缩速度更重的话适合这两种。\

  • 压缩格式是否可分割,MR任务需要将数据分割成多个部分发送到多个map任务上,Hadoop需要知道文件中记录的边界才可以分割。对于文本文件,每一行是一条记录,但是GZip和Snappy即将这些边界信息掩盖掉, 不过BZip2和LZO提供了块级别的压缩,也就是每个块含有完整的信息 。

  • 用户创建文件时,可以将文件分割成期望的文件大小,通常输出文件的个数等于reducer的个数,也就是如果用户使用了N个reducer那么通常会得到N个输出文件。

  • InputFormat中定义了如何读取划分,以及如何将划分分割成记录,而OutputFormat中定义了如何将这些划分写回到文件或控制台输出中 。

开启中间压缩

  • 对中间数据进行压缩可以减少job中map和reduce task间的数据传输量,对于中间数据压缩,选择一个低CPU开销的编/解码器要比选择一个压缩率高的编解码器重要 。hive.exec.compress.intermediate的默认只是false,关闭中间压缩,设置为true开启中间压缩。对于其他Hadoop job中间数据压缩的属性是mapred.compress.map.output.

  • Hadoop默认的编解码器是 DefaultCodec , 可以通过修改mapred.map.output.compression.codec的值来修改编解码器 , 在mapred-site.xml中或者hive-site.xml中修改。SnappyCodec是一个比较好的中间压缩编解码器,他可以很好的结合低CPU和好的压缩执行效率 。

<property> 
<name>mapred.map.output.compression.codec</name> 
<value>org.apache.hadoop.io.compress.SnappyCodec</value> 
<description> This controls whether intermediate files produced by Hive 
between multiple map-reduce jobs are compressed. The compression codec 
and other options are determined from hadoop config variables 
mapred.output.compress* </description> 
</property> 

最终输出结果压缩

  • 当hive输出写入表中时,输出内容也可以进行压缩,属性是 hive.exec.compress.output 控制。默认为false关闭。其他hadoop job通过mapred.output.compress来开启。

  • 输出文件使用GZip进行压缩比较合适,GZip可以大幅度降低文件的大小,但是GZip压缩的文件对于后面的MR job是不可分割的。

sequence file存储格式

  • sequence file存储格式可以将一个文件划分成多个块,然后采用一种可分割的方式对块进行压缩。

  • CREATE TABLE tablename stored as sequencefile;

  • sequence file提供三种压缩方式:NONE、RECORD和BLOCK,默认是记录级别。

# sequence file的压缩类型 
<property> 
<name>mapred.output.compression.type</name> 
<value>BLOCK</value> 
<description>If the job outputs are to compressed as SequenceFiles, 
how should they be compressed? Should be one of NONE, RECORD or BLOCK. 
</description> 
</property> 

使用压缩实践

开启中间数据压缩

  • set hive.exec.compress.intermediate=true;

  • set mapred.map.output.compression.code=org.apache.hadoop.io.compress.GZipCodec; 设置编解码器

开启输出结果数据压缩

  • set hive.exec.compress.output=true;

# 数据格式 
user/hive/warehouse/test3_copy/000000_0.deflate 

使用senquence file

  • set mapred.output.compression.type=BLOCK; 开启块类型压缩

  • set hive.exec.compress.output=true; 开启输出结果压缩

  • set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;设置Gzip编解码器

  • 创建sequence file文件存储格式

create table sequence_table stored as sequencefile as select * from test2; 
  • sequnece file是二进制格式,文件格式为SEQ[]inputformat[]outputFormat格式[]编解码器[]

  • dfs -text /user/hive/warehouse/sequence_table/000000_0;查看数据

直接数据压缩和最终数据压缩实战

# 设置压缩map端编解码器 
hive> set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec; 
# 开启中间数据压缩 
hive> set hive.exec.compress.intermediate=true; 
# 设置sequnecefile压缩类型 
hive> set mapred.output.compression.type=BLOCK; 
# 开启输出数据压缩类型 
hive> set hive.exec.compress.output=true; 
# 设置输出数据压缩编解码器 
hive> set mapred.output.compression.codec 
 =org.apache.hadoop.io.compress.GzipCodec; 

hive> CREATE TABLE final_comp_on_gz_int_compress_snappy_seq 
  > ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' 
  > STORED AS SEQUENCEFILE AS SELECT * FROM a; 

存档分区

  • Hadoop中有一种存储格式名为HAR,也就是Hadoop Archive (Hadoop归档文件)的简写。 一个HAR文件就像在HDFS文件系统中的一个TAR文件一样是一个单独的文件 。不过,其内部可以存放多个文件和文件夹 。在一些使用场景下,较旧的文件夹和文件比较新的文件夹和文件被访问的概率要低很多。如果某个特定的分区下保存的文件有成千上万的话,那么就 需要HDFS中的NameNode消耗非常大的代价来管理这些文件。通过将分区下的文件归档成一个巨大的,但是同时可以被Hive访问的文件,可以减轻NameNode的压力 。不过其缺点是, HAR文件查询效率不高;同时,HAR文件并非是压缩的,因此也不会节约存储空间 。

测试

  • 创建分区表

create table hive_test(line string) paritioned by(folder string); 
  • 增加静态分区

alter table hive_test add parition(folder='doc'); 
  • 加载本地数据

load data local inpath '${env:HIVE_HOME}/RELEASE_NOTES.txt' overwrite into table hive_test partition(folder='doc'); 
load data local inpath '${env:HIVE_HOME}/README.txt' overwrite into table hive_test partition(folder='doc'); 

开启归档

  • set hive.archive.enabled=true;

  • alter table hive_test archive partition(folder='doc'); 开启归档

  • Hadoop归档方式

hadoop archive -archiveName test.har -p /user/hive/warehouse/hive_test/folder=doc /user/hive/warehouse/hive_test/folder=doc 
  • alter table hive_test unarchive partion(folder='doc');将HAR文件提取出来放入HDFS

最后更新于