【问题标题】:Splitting large files in half将大文件分成两半
【发布时间】:2019-09-04 00:59:39
【问题描述】:

tl;dr: 我需要一种将 5 GB / ~11m 行文件分成 ~ 一半(或三分之一)的方法,同时准确跟踪我创建的每个文件,当然不破坏任何行,所以我可以同时处理两个文件

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

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

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

尽管我刚才说过,我想我在我的文件上运行 wc -l file,将其除以 n,将结果向上舍入 ,然后使用 split 来打破归档到那么多行。那应该总是给我准确的 n 个文件。我只能知道我有fileafileb 等等。

我想问题最终是,有没有更好的方法来处理这个问题?也许还有另一个实用程序会以与我正在做的事情更兼容的方式进行拆分。或者也许还有另一种我完全忽略的方法。

【问题讨论】:

  • 我不完全理解这个问题。如果你有 300 个这样的文件,为什么不并行加载它们呢?根据您的描述,我认为没有必要拆分单个文件。
  • 您有 300 个 5GB 的文件...作为 JSON?你可以在 PHP 中加载它吗?
  • split -n 不适合你吗? man7.org/linux/man-pages/man1/split.1.html
  • I've optimized the hell out of parsing script and it's reached it's speed limit. But it's still a single-threaded script running for about 20 hours on a 16 core server. - 你已经达到了 PHP 的极限,请用 C++ 重写该特定部分,然后让 php 脚本通过 shell_exec() 或其他方式调用你的 c++ 程序。
  • 每个文件都是5GB?您不必减少 5GB,您应该能够一次加载 1 个文件并确保 php 在加载下一个文件之前清除内存 - 确保它在运行时使用超过 5GB 的 RAM,但是无论如何,一个 16C 的服务器可能有很多内存。

标签: php mysql parsing split command


【解决方案1】:

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

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

然后使用 GNU 版本的 split,它有一个额外的 --filter 选项,允许在更小的空间内处理单个数据块,因为它不需要创建任何临时文件:

split --filter='shell_command'

您的过滤命令应该从标准输入读取:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 2013-12-06
    • 2012-05-26
    • 1970-01-01
    • 2015-04-17
    • 2015-12-02
    • 2020-07-20
    相关资源
    最近更新 更多