Hadoop的压缩和输入分片。

        在考虑如何压缩将由MapReduce处理的数据时,理解这些压缩格式是否支持切分(splitting)是非常重要的。以一个存储在HDFS文件系统中且压缩前大小为1GB的文件为例。如果HDFS的块大小设置为128MB,那么该文件将被存储在8个块中,把这个文件作为输入数据的MapReduce作业,将创建8个输入分片,其中每个分片作为一个单独的map任务的输入被独立处理。

        现在想象一下,文件是经过gzip压缩的,且压缩后文件大小的1GB。与以前一样,HDFS将这个文件保存为8个数据块。但是,将每个数据块单独作为一个输入分片是无法实现工作的,因为无法实现从gzip压缩数据流的任意位置读取数据,所以让map任务独立于其他任务进行数据读取是行不通的。gzip格式使用DEFLATE算法来存储压缩后的数据,而DEFLATE算法将数据存储在一系列连续的压缩块中。问题在于每个块的起始位置并没有以任何形式标记,所以读取时无法从数据流的任意当前位置前进到下一块的的起始位置读取下一个数据块,从而实现与整个数据流的同步。由于上述原因,gzip并不支持文件切分。

        在这种情况下,MapReduce会采用正确的做法,他不会尝试切分gzip压缩文件,因为他知道输入是gzip压缩文件(通过文件扩展名看出)且gzip不支持切分。这是可行的,但牺牲了数据的本地性:一个map任务处理8个HDFS块,而其中大多数块并没有存储在执行该map任务的节点上。而且,map任务数越少,作业的粒度就较大,因而运行的时间可能会更长。

        在前面假设的例子中,如果文件是通过LZO压缩的,我们会面临相同的问题,因为这个压缩格式也不支持数据读取和数据流同步。但是,在预处理LZO文件的时候使用包含在Hadoop LZO库文件中的索引工具是可能的。该工具构建了切分点索引,如果使用恰当的MapReduce输入格式可有效实现文件的可切分特性。

        另一方面,bzip2文件提供不同数据块之间的同步标识(pi的48位近似值),因而它支持切分。

你可能感兴趣的:(Hadoop)