多核 gzip 解压缩,将输出文件 (csv) 拆分为 1Gb/文件

Posted

技术标签:

【中文标题】多核 gzip 解压缩,将输出文件 (csv) 拆分为 1Gb/文件【英文标题】:Multicore gzip uncompression with spliting output file (csv) to parts by 1Gb/file 【发布时间】:2015-09-07 17:03:42 【问题描述】:

我有 10Gb gzip 存档(未压缩大约 60Gb)。

有没有办法使用多线程 + 即时将输出拆分为 1Gb/部分(n 行/部分,maybe)的部分?

如果我这样做:

pigz -dc 60GB.csv.gz | dd bs=8M skip=0 count=512 of=4G-part-1.csv

我可以获得一个 4Gb 的文件,但它并不关心总是从下一行开始,所以我的文件中的行不会正确结束。

另外,正如我所注意到的,我的带有持久磁盘的 GCE 实例的最大块大小为 33kb,所以我实际上不能使用上述命令,但必须打印如下内容:

pigz -dc 60GB.csv.gz | dd bs=1024 skip=0 count=4194304 of=4G-part-1.csv

pigz -dc 60GB.csv.gz | dd bs=1024 skip=4194304 count=4194304 of=4G-part-2.csv

pigz -dc 60GB.csv.gz | dd bs=1024 skip=$((4194304*2)) count=4194304 of=4G-part-3.csv

所以,我必须采取一些技巧来始终从新行开始文件..

更新:

zcat 60GB.csv.gz |awk 'NR%43000000==1x="part-"++i".csv";print > x'

成功了。

【问题讨论】:

你有足够的内存(即~10GB)来保存这个文件吗? 我会得到一些,如果我能找到一个工作方法来做到这一点。 我建议你先获取内存,然后看看性能如何。当您为应用程序提供足够的内存时,这个问题可能会随着您获得的性能而变得无效。尤其是“大数据”,当内存不足时,整个系统就会瘫痪。 【参考方案1】:

根据您在问题中提到的尺寸,您似乎获得了大约 6 比 1 的压缩率。这对于文本来说似乎不太好,但无论如何......

正如 Mark 所说,您不能只是将中间流浸入 gz 文件并期望在新行上着陆。您的 dd 选项将不起作用,因为 dd 仅复制字节,它不检测压缩换行符。如果索引超出此范围,以下命令行解决方案可能会有所帮助:

$ gzcat 60GB.csv.gz | awk -v n=1 '!NR%20000000n++ print|("gzip>part-"n".gz")'

这会解压缩您的文件,以便我们可以计算行数,然后处理流,每 20000000 行更改输出文件名。您可以在上面代码中看到“gzip”的位置调整重新压缩选项。

如果您不想压缩输出,可以简化该行的最后一部分:

$ gzcat 60GB.csv.gz | awk -v n=1 '!NR%3500000n++ print>("part-"n".csv")'

您可能需要调整行数才能获得接近目标文件大小的内容。

请注意,如果您的 shell 是 csh/tcsh,您可能必须转义 awk 脚本中的感叹号以避免它被解释为历史引用。

更新

如果您想了解脚本正在执行的操作的状态,awk 可以做到这一点。这样的事情可能会很有趣:

$ gzcat 60GB.csv.gz | awk -v n=1 '!NR%3500000n++ !NR%1000printf("part=%d / line=%d\r",n,NR) print>("part-"n".csv")'

这应该会向您显示当前部分和每千行的行号。

【讨论】:

tnx, m8, 这是一个很好的.. 但是你能再帮我一次吗,我对 awk 不是很熟悉,只是无法获得创建多个文件的命令2000000 行:它只创建一个大文件 part-1.csv 并将所有内容打印到它。 人力资源部。那很奇怪。无论如何,文件中有多少行? (gzcat file.gz | wc -l 会告诉你。)条件!NR%20000000 确实应该每两千万行评估一次为真。您可以尝试将数量减少到容易看到的程度,例如几千个,然后看看是否有很多文件? 我已经用 awk 命令的变体更新了答案,它应该会给你关于运行进度的反馈。【参考方案2】:

除非它是专门为这种操作准备的,或者除非为此目的建立了索引,否则不会。 gzip 格式本质上需要在流中的任何点之前解压缩数据,以便在流中该点之后解压缩数据。所以不能并行化。

解决方法是 a) 重新压缩带有同步点的 gzip 文件并保存这些位置,或者 b) 遍历整个 gzip 文件并在这些点处创建具有先前上下文的另一个入口点文件。

对于a),zlib 提供Z_FULL_FLUSH 操作,在流中插入同步点,您可以从这些点开始解压,而无需之前的历史记录。您可能希望谨慎地创建此类点,因为它们会降低压缩率。

对于 b),zran.c 提供了如何在 gzip 文件中构建索引的示例。您需要按顺序遍历流一次以构建索引,但完成此操作后,您可以在保存的位置开始解压。

【讨论】:

我heardpigz 可以提供类似多线程的方式来解压gz,因为它使用单线程解压的同时额外启动了3个线程进行读、写和校验计算。 哦,对不起,我好像没明白你的意思(我的英语不够好) pigz 在多处理器解压时只提供很小的加速,因为 gzip 流的串行特性。然而,在 n 处理器上进行压缩时,pigz 提供了 n 的加速因子。

以上是关于多核 gzip 解压缩,将输出文件 (csv) 拆分为 1Gb/文件的主要内容,如果未能解决你的问题,请参考以下文章

Linux 压缩与解压缩工具gzip/gunzip

gzip 命令

gzip

0027压缩解压缩及归档工具

如何以 csv 格式导出 redhsift 卸载命令的输出?

Linux命令(28):gzip/gunzip命令-压缩和解压