Hive的压缩方法

187 阅读4分钟

前言

Hive的一个独特功能就是:Hive不会强制要求将数据转换成特定的格式才能使用。Hive利用Hadoop的InputFormat API来从不同的数据源读取数据,例如文本格式、sequence文件格式,甚至用户自定义格式。同样地,使用OutputFormat API也可以将数据写成不同的格式。

尽管Hadoop的文件系统支持对于非压缩数据的线性拓展存储,但是对数据进行压缩还是有很大好处的。压缩通常都会节约客观的磁盘空间,例如,基于文本的文件可以压缩40%甚至更高比例。压缩同样可以增加吞吐量和性能。这看上去似乎并不和常理,因为压缩和解压缩会增加额外的CPU开销,不过,通过减少载入内存的数据量而提高I/O吞吐量会更加提高网络传输性能。

Hadoop的job通常是I/O密集型而不是CPU密集型,如果是这样的话,压缩可以提高性能。不过,如果用户的job是CPU密集型的话,那么使用压缩可能会降低执行性能。确定是否进行压缩的唯一方式就是尝试不同的选择,并测量对比执行效果。

1、选择一种压缩编/解码器

使用压缩的方式是可以最小化所需要的磁盘存储空间,以及减小磁盘和网络I/O操作。不过,文件压缩过程和解压过程会增加CPU开销。因此,对于压缩密集型的job最好使用压缩,特别是有额外的CPU资源或磁盘存储空间比较稀缺的情况。

所有的最新的那些Hadoop版本都已经内置支持GZIP和BZIP压缩方案了,包括加速对这些格式的压缩和解压缩的本地Linux库。绑定Snappy压缩是最近才增加的,不过,如果用户当前使用的Hadoop版本不支持该功能的话,那么自行增加相关的库即可。另外,还有一种常用的压缩方案,即LZO压缩。

那么,为什么我们需要不同的压缩方案呢? 每一个压缩方案都在压缩/解压缩毒和压缩率间进行权衡。BZip2压缩率最高,但是同时需要消耗最多的CPU开销。GZip是压缩率和压缩/解压缩速度上的下一个选择。因此,如果磁盘空间利用率和I/O开销都需要考虑的话,那么这2种压缩方案都是有吸引力的。

LZO和Snappy压缩率相比前面的2种要小但是压缩/解压速度更快,特别是解压缩过程。如果相对于磁盘空间和I/O开销,频繁读取数据所需的解压缩速度更重要的话,那么它们将是不错的选择。

另一个需要考虑的因素是压缩格式的文件是否是可分割的。MapReduce需要将非常大的输入文件分割成多个划分(通常一个文件块对应一个划分,也就是128M的倍数),其中每个划分会被分发到一个单独的map进程中。只有当Hadoop知道文件中记录的边界时才可以进行这样的分割。对于文本文件,每一行都是一条记录,但是GZip和Snappy将这些边界信息掩盖掉了。不过,BZip2和LZO提供了块(BLOCK)级别的压缩,也就是每个块都都含有完整的记录信息,因此Hadoop可以在块边界级别对这些文件进行划分。

2、开启中间压缩

对中间数据进行压缩可以减少job中map和reduce task间的数据传输量。对于中间数据压缩,选择一个低CPU开销的编/解码器要比选择一个压缩率高的编/解码器要重要得多。属性 hive.exec.compress.intermediate的默认值是false,如果要开启中间压缩,就需要将这个属性值修改为默认值true

Hadoop压缩默认的编/解码器是DefaultCodec。可以通过修改属性 mapreduce.map.output.compress.codec来修改编/解码器。这是一个Hadoop配置项,可以在%HADOOP_HOME/conf/mapred-site.xml文件中或$HIVE_HOME/conf/hive-site.xml

set hive.exec.compress.intermediate = true;
set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec; (建议开启)
set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.LzoCodec; (建议开启,需单独安装)

3、最终输出结果压缩

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

set hive.exec.compress.output=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.BZip2Codec;  
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec; (建议开启)
set mapred.output.compression.codec= org.apache.hadoop.io.compress.LzoCodec; (建议开启,需单独安装)