将大文件分成两半

时间:2019-04-13 12:40:21

标签: php mysql parsing split command

tl; dr::我需要一种在大约一半(或三分之二)的位置上分割5 GB /〜11m行文件的方法,同时要跟踪我创建的每个文件,当然也不要中断任何行,所以我可以一次处理两个文件

我有一组300个非常大的类似json的文件,需要定期使用php脚本进行解析。每个文件约解压缩5 GB。我已经从解析脚本中优化了地狱,达到了速度极限。但是它仍然是单线程脚本,在16核心服务器上运行大约20个小时。

我想将每个文件分成大约一半,并一次运行两个解析脚本,以“伪造”多线程并加快运行时间。我可以在sql数据库中的线程之间存储全局运行时信息和“消息”。这样一来,总的运行时间将减少一半,有一个线程下载文件,另一个线程将其解压缩,再有两个线程并行地将它们加载到sql中。

这部分实际上很简单,我遇到的问题是拆分要解析的文件。我知道有一个split工具可以根据KB或行数将文件分解为大块。问题是,这对我来说不太有效。我需要将这些文件整齐地分成两半(或三分之二或四分之一)。并且没有多余的数据进入一个额外的文件。我需要确切地知道split命令已创建了哪些文件,以便可以在sql表中记录简单文件,以便解析脚本可以知道哪些文件已准备好进行解析。如果可能的话,我什至希望避免在此过程中运行wc -l。这可能无法实现,但是每个文件200个文件大约需要7秒钟,这意味着需要35分钟的运行时间。

尽管我刚才说了什么,但我想我在文件上运行wc -l file,将其除以 n ,将结果向上取整,并使用split将文件分成很多行。那应该总是给我确切的 n 个文件。比起我,我只能知道生病的有fileafileb等。

我想问题最终是,有没有更好的方法来解决这个问题?也许还有另一个实用程序,它将以与我正在做的工作更加兼容的方式进行拆分。也许还有我完全忽略的另一种方法。

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,要找到解决方案并不容易。

首先,您需要使用jq将JSON转换为字符串格式。

然后使用split的GNU版本,它具有一个额外的--filter选项,由于不需要创建任何临时文件,因此它可以在更少的空间中处理单个数据块:

split --filter='shell_command'

您的过滤器命令应从stdin中读取:

jq -r '' file.json | split -l 10000 --filter='php process.php'

-l会告诉split一次处理10000行。

process.php文件中,您只需要read from stdin并做您想做的任何事情。