我有10Gb gzip存档(未压缩约60Gb)。
有没有办法解决这个文件的多线程+在飞行分裂输出上的部分1Gb /部分(n行/部分,maybe)?
如果我这样做:
id
我可以获得一个4Gb文件,但它并不关心从下一行开始,所以我文件中的行不会正常结束。
另外,正如我所说,我的持有磁盘的GCE实例的块大小最大为33kb,因此我实际上不能使用上面的命令,但必须打印如下内容:
pigz -dc 60GB.csv.gz | dd bs=8M skip=0 count=512 of=4G-part-1.csv
所以,我必须制定一些技巧来始终从新行启动文件..
更新
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
做了这个伎俩。
答案 0 :(得分:1)
除非为此类操作特别准备,或者除非为此目的而构建索引,否则不行。 gzip格式固有地要求在流中的任何点之前解压缩数据,以便在流中的该点之后解压缩数据。所以它无法并行化。
出路是a)用同步点重新压缩gzip文件并保存这些位置,或b)遍历整个gzip文件一次,并在这些点创建另一个带有前一个上下文的入口点文件。
对于a),zlib提供了Z_FULL_FLUSH
个操作,可以在流中插入同步点,您可以从中开始解压缩,而不需要以前的历史记录。您可能希望谨慎地创建这些点,因为它们会降低压缩率。
对于b),zran.c提供了如何在gzip文件中构建索引的示例。您需要按顺序遍历流一次以构建索引,但是完成后,您可以在已保存的位置开始解压缩。
答案 1 :(得分:1)
根据您在问题中提到的尺寸,看起来您的压缩率约为6比1。这对文本来说似乎不太好,但无论如何......
正如马克所说,你不能只是将中间流放入你的gz文件中,并希望登陆新行。您的dd
选项不起作用,因为dd只复制字节,它不会检测压缩的换行符。如果索引超出此范围,则以下命令行解决方案可能有所帮助:
$ gzcat 60GB.csv.gz | awk -v n=1 '!NR%20000000{n++} {print|("gzip>part-"n".gz")}'
这会解压缩您的文件,以便我们可以计算行数,然后处理流,每20000000行更改输出文件名。你可以调整你在上面的代码中看到“gzip”的再压缩选项。
如果您不希望压缩输出,可以简化该行的最后部分:
$ gzcat 60GB.csv.gz | awk -v n=1 '!NR%3500000{n++} {print>("part-"n".csv")}'
您可能需要使用行数来获得接近您所希望的文件大小的内容。
请注意,如果您的shell是csh / tcsh,则可能必须转义awk脚本中的感叹号,以避免将其解释为历史引用。
<强>更新强>:
如果您想获得脚本正在执行的操作的状态,awk可以做到这一点。这样的事情可能很有趣:
$ gzcat 60GB.csv.gz | awk -v n=1 '!NR%3500000{n++} !NR%1000{printf("part=%d / line=%d\r",n,NR)} {print>("part-"n".csv")}'
这应该显示每千行的当前部分和行号。