随机访问gzip文件?

我有一个非常大的文件压缩坐在磁盘上的gzip。 生产环境是基于“云”的,所以存储性能很差,但是CPU很好。 以前我们的数据处理stream水线是以gzip -dc从磁盘上传输数据开始的。

现在,为了平行工作,我想运行多个stream水线,每个stream水线都需要一对字节偏移量 – 开始和结束 – 然后取出文件的大块。 用一个简单的文件,这可以实现headtail ,但我不知道如何高效地使用压缩文件; 如果我将gzip -dc和pipe放入head ,则朝向文件尾部的偏移对将缓慢地解压缩,从而浪费地search整个文件。

所以我的问题实际上是关于gzipalgorithm的 – 理论上可以在底层文件中寻找一个字节偏移量,或者得到一个任意大小的块,而没有将整个文件解压到那个点的全部影响? 如果不是,我怎么能有效地分割一个文件,以便多个进程进行“随机”访问,同时最大限度地减lessI / O吞吐量开销?

你不能用gzip做到这一点,但是你可以用bzip2来做到这一点,而不是基于流的块,这就是Hadoop DFS如何拆分和并行化在MapReduce算法中使用不同映射器的大文件的读取。 也许这是有道理的重新压缩你的文件为bz2,所以你可以利用这一点; 这将比一些特殊的方式来组合文件更容易。

我在Hadoop中找到了实现这个的补丁: https : //issues.apache.org/jira/browse/HADOOP-4012

这里是关于主题的另一篇文章: 在Hadoop中读取BZip2文件

也许浏览Hadoop源代码会给你一个如何按块读取bzip2文件的想法。

是的,您可以通过按顺序读取整个东西并构建索引来随机访问gzip文件。 参见zlib发行版中的examples / zran.c。

如果您正在控制创建gzip文件,那么您可以通过构建随机访问入口点并在压缩时构建索引来优化文件。

您也可以使用Z_SYNC_FLUSH然后在zlib的deflate()使用Z_SYNC_FLUSH创建一个带有标记的gzip文件,以插入两个标记,并使下一个块独立于以前的数据。 这会减少压缩,但是如果你不经常这样做的话,压缩比不会太大。 例如,每兆字节应该有非常小的影响。 然后,您可以搜索一个9字节的标记(与bzip2的六字节标记相比,错误的可能性要小得多): 00 00 ff ff 00 00 00 ff ff

gzip确实希望能够从头开始流式传输文件。 你不能从中间开始。

你可以做的是将文件分割成块,用gzip分段压缩,然后连接在一起。 您可以选择任意大小,例如10MB或100MB。 然后从包含所需字节偏移量的部分开始进行解压缩。 由于gzip一个鲜为人知的特性(就是解压缩一个文件,这个文件是几个较小的gzip文件的连接产生的输出与解压缩每个较小的文件并将结果连接在一起相同),分段压缩的大文件也可以工作与标准的gzip -d / gunzip如果你下载整个事情。

棘手的部分:你必须维护一个包含大文件中每个压缩块的开始的字节偏移量的索引。