《Hadoop权威指南:大数据的存储与分析》—5.2.2 压缩和输入分片
5.2.2 压缩和输入分片
在考虑如何压缩将由MapReduce处理的数据时,理解这些压缩格式是否支持切分(splitting)是非常重要的。以一个存储在HDFS文件系统中且压缩前大小为1 GB的文件为例。如果HDFS的块大小设置为128 MB,那么该文件将被存储在8个块中,把这个文件作为输入数据的MapReduce作业,将创建8个输入分片,其中每个分片作为一个单独的map任务的输入被独立处理。
现在想象一下,文件是经过gzip压缩的,且压缩后文件大小为1 GB。与以前一样,HDFS将这个文件保存为8个数据块。但是,将每个数据块单独作为一个输入分片是无法实现工作的,因为无法实现从gzip压缩数据流的任意位置读取数据,所以让map任务独立于其他任务进行数据读取是行不通的。gzip格式使用DEFLATE算法来存储压缩后的数据,而DEFLATE算法将数据存储在一系列连续的压缩块中。问题在于每个块的起始位置并没有以任何形式标记,所以读取时无法从数据流的任意当前位置前进到下一块的起始位置读取下一个数据块,从而实现与整个数据流的同步。由于上述原因,gzip并不支持文件切分。
在这种情况下,MapReduce会采用正确的做法,它不会尝试切分gzip压缩文件,因为它知道输入是gzip压缩文件(通过文件扩展名看出)且gzip不支持切分。这是可行的,但牺牲了数据的本地性:一个map任务处理8个HDFS块,而其中大多数块并没有存储在执行该map任务的节点上。而且,map任务数越少,作业的粒度就较大,因而运行的时间可能会更长。
在前面假设的例子中,如果文件是通过LZO压缩的,我们会面临相同的问题,因为这个压缩格式也不支持数据读取和数据流同步。但是,在预处理LZO文件的时候使用包含在Hadoop LZO库文件中的索引工具是可能的,你可以在5.2.1所列的Google 和GitHub网站上获得该类库。该工具构建了切分点索引,如果使用恰当的MapReduce输入格式可有效实现文件的可切分特性。
另一方面,bzip2文件提供不同数据块之间的同步标识(pi的48位近似值),因而它支持切分。可以参见表5-1,了解每个压缩格式是否支持切分。
应该使用哪种压缩格式?
Hadoop应用处理的数据集非常大,因此需要借助于压缩。使用哪种压缩格式与待处理的文件的大小、格式和所使用的工具相关。下面有一些建议,大致是按照效率从高到低排列的。
l 使用容器文件格式,例如顺序文件(见5.4.1节)、Avro数据文件(参见12.3节)、ORCFiles(见5.4.3节)或者Parquet文件(参见13.2节),所有这些文件格式同时支持压缩和切分。通常最好与一个快速压缩工具联合使用,例如LZO,LZ4,或者Snappy。
l 使用支持切分的压缩格式,例如bzip2(尽管bzip2非常慢),或者使用通过索引实现切分的压缩格式,例如LZO。
l 在应用中将文件切分成块,并使用任意一种压缩格式为每个数据块建立压缩文件(不论它是否支持切分)。这种情况下,需要合理选择数据块的大小,以确保压缩后数据块的大小近似于HDFS块的大小。
l 存储未经压缩的文件。
对大文件来说,不要使用不支持切分整个文件的压缩格式,因为会失去数据的本地特性,进而造成MapReduce应用效率低下。
- 点赞
- 收藏
- 关注作者
评论(0)