我用gzip坐在磁盘压缩非常大的文件。 生产环境是“云”为基础的,所以存储性能是可怕的,但CPU是好的。 以前我们的数据处理流水线开始gzip -dc
流中的数据从磁盘。
现在,为了parallelise的工作,我想运行多条管线,每取一对字节偏移 - 开始和结束 - 并且采取文件的该块。 与文本文件,这可能与实现head
和tail
,但我不知道如何与一个压缩文件有效地做到这一点; 如果我gzip -dc
和管进入head
,偏移对那些向文件的末尾将涉及浪费,通过整个文件,寻求,因为它是慢慢的解压缩。
所以我的问题实际上是关于gzip算法 - 是理论上可以寻求一个字节底层文件偏移或获取它的一个任意块,无需解压整个文件到这一点的全面影响? 如果不是,怎么回事我可能有效,同时最小化I / O吞吐量的开销分区被多个进程“随机”访问的文件?
你不能这样做,用gzip,但你可以用bzip2,这是块而不是基于流的做到这一点 - 这是Hadoop的DFS是如何拆分和并行化的,在它的MapReduce算法不同映射器大文件的读取。 也许这将是有意义的重新压缩文件作为BZ2,所以你可以利用这一点; 这将是比一些特别的方式来块了文件更容易。
我发现,在Hadoop的实现这一点,这里的补丁: https://issues.apache.org/jira/browse/HADOOP-4012
下面是关于该主题的另一个帖子: Hadoop中读BZip2压缩文件
或许浏览Hadoop的源代码,会给你的如何通过块读取的bzip2文件中的想法。
是的,你可以通过阅读整个事情顺序一次性和建立索引随机访问gzip文件。 见例子/ zran.c在zlib的分布。
如果你是在创建gzip文件的控制,那么你可以通过建立在随机访问的入口点优化用于此目的的文件,并建立索引,同时压缩。
您也可以通过创建一个标记gzip文件Z_SYNC_FLUSH
随后Z_FULL_FLUSH
在zlib的的deflate()
,以插入两个标记,使下一个块独立于以前的数据。 这将减少压缩,但不是很多,如果你不这样做太频繁。 例如,每兆字节应该具有的影响非常小。 然后,你可以搜索一个九字节标记(比bzip2的六个字节的标记可能误报少得多): 00 00 ff ff 00 00 00 ff ff
。
gzip
事实上确实希望能够从一开始就流的文件。 你不能在中间开始。
你可以做的是打破了文件到被分段与压缩块gzip
,然后连接在一起。 你可以选择你喜欢的每一件任何尺寸,例如10MB或100MB。 然后,您解压缩起始于一个包含offset您所需要的字节块的开始。 由于一个鲜为人知的特征gzip
(其是解压缩的文件是几个较小gzip文件的级联产生相同的输出作为解压缩每个较小的文件,并一起串接结果)压缩大文件也将工作分段与标准gzip -d
/ gunzip
,如果你下载了整个事情。
最棘手的部分:你必须保持包含该字节的大文件中的每个压缩块的开始偏移的索引。