随机访问gzip文件?

Cer*_*era 23 unix concurrency streaming gzip

我有一个非常大的文件压缩与gzip坐在磁盘上.生产环境基于"云",因此存储性能很差,但CPU很好.以前,我们的数据处理流程始于gzip -dc从磁盘上传输数据.

现在,为了并行工作,我想运行多个管道,每个管道都需要一对字节偏移 - 开始和结束 - 并获取该文件的块.使用普通文件,这可以通过head和实现tail,但我不知道如何使用压缩文件有效地完成它; 如果我gzip -dc和管道进入head,文件末尾的偏移对将涉及浪费地搜索整个文件,因为它慢慢解压缩.

所以我的问题实际上是关于gzip算法 - 理论上是否有可能在底层文件中寻找一个字节偏移量或得到它的任意一块,而没有解压缩整个文件到那一点的全部含义?如果没有,我可以如何有效地将文件分区为多个进程的"随机"访问,同时最小化I/O吞吐量开销?

Mar*_*ler 23

是的,您可以通过顺序读取整个事物并构建索引来随机访问gzip文件.请参阅zlib发行中的examples/zran.c.

如果您可以控制创建gzip文件,则可以通过构建随机访问入口点并在压缩时构造索引来为此目的优化文件.

您还可以使用标记创建带有标记的gzip文件,Z_SYNC_FLUSH然后Z_FULL_FLUSH在zlib deflate()中插入两个标记并使下一个块独立于先前的数据.这样可以减少压缩,但如果不经常这样做,则会减少压缩.例如,每兆字节应该影响很小.然后,你可以搜索一个九字节标记(比bzip2的六个字节的标记可能误报少得多)00 00 ff ff 00 00 00 ff ff.

  • 有没有zran的使用教程;即我如何使用它来索引一个 gzipped 文件并随后访问我选择的行号(或字符号?)?我认为这是我一直在寻找的灵丹妙药。 (2认同)
  • @SumitKumarGhosh 我不明白你的问题。也许您应该提出一个新问题而不是将其放在评论中。 (2认同)

And*_*Mao 16

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

我找到了在Hadoop中实现此功能的补丁,请访问:https://issues.apache.org/jira/browse/HADOOP-4012

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

也许浏览Hadoop源代码可以让您了解如何按块读取bzip2文件.

  • @MarkAdler bzip2 更适合这项任务,因为您不必像使用 gzip 那样从头开始阅读。您可以潜入中间,寻找块边界。来自http://www.bzip.org/1.0.5/bzip2-manual-1.0.5.html:*每个块的压缩表示由48位模式分隔,这使得可以找到块边界具有合理的确定性。* (2认同)

Cel*_*ada 10

gzip事实上,我们希望能够从一开始就传输文件.你无法从中间开始.

你可以做的是将文件分解成块,这些块被分段压缩,gzip然后连接在一起.您可以为每件作品选择任何尺寸,例如10MB或100MB.然后从包含所需字节偏移的片段的开头开始解压缩.由于一个鲜为人知的特性gzip(解压缩文件是几个较小的gzip压缩文件的串联产生与解压缩每个较小文件相同的输出并将结果连接在一起),分段压缩的大文件也可以使用标准gzip -d/ gunzip如果你下载整个东西.

棘手的部分:您必须维护一个索引,该索引包含大文件中每个压缩块的开头的字节偏移量.

  • 您可以从gzip流的中间开始,只要您从头开始解压缩它并构造入口点.或者,如果您在压缩它时创建了入口点. (2认同)

cir*_*eos 5

FWIW:我在 zlib 的zran.c上开发了一个命令行工具,它为 gzip 文件创建索引,允许在其中进行非常快速的随机访问: https: //github.com/circulosmeos/gztool

它甚至可以为仍在增长的 gzip 文件创建索引(例如 rsyslog 直接以 gzip 格式创建的日志),从而在实践中减少索引创建时间为零。请参阅 -S(监督)选项。