高效地将数百万个 JSON 文件附加到单个文件中

Posted

技术标签:

【中文标题】高效地将数百万个 JSON 文件附加到单个文件中【英文标题】:Append millions of JSON files into a single file efficiently 【发布时间】:2016-10-13 15:21:55 【问题描述】:

我有数百万个 json 文件,我需要将它们作为 json dicts 列表附加到单个 json 文件中:

每个 json 文件都包含以下 dict:


  "finent": "abc",
  "findeplabel": "lbl",

应该合并成一个 json 文件作为字典列表:

[
  "finent": "abc",
  "findeplabel": "lbl",
,

  "finent": "abc",
  "findeplabel": "lbl",
...]

使用“cat”命令等的问题是输入文件数量巨大,最终文件大小可能>8GB。

低效版本:cat *.json|replace "\n" "," 那么,为了提高效率,理想地同时合并 json 文件的最有效方法是什么?

【问题讨论】:

为什么叫cat效率低?在您看来,它在这里执行的操作的哪些部分(在另一个文件末尾连接一个文件)可以更有效地完成? (另外:为什么是 Python 标签?) @RadLexus 处于较低级别,只是连接文件而不将其复制到新文件描述符 还有在发射每个文件输出后添加逗号“,”的操作,可以更有效的节省后面的pass。 replace是一个用于替换字符串的python程序 “进入较低级别,只是连接文件而不将其复制到新的文件描述符中” Unix 内核所说的“低级别”甚至是什么?我根本不知道那会如何工作。当整个操作是 IO 绑定时,并发是相当没有意义的。 【参考方案1】:

以下脚本 (slurp.sh) 举例说明了使用 bash 的直接方法。 它可以很容易地根据相关 JSON 文件的指定方式进行修改。

我怀疑开发和测试更复杂的解决方案所花费的时间比这样做会节省执行时间要长得多,但是如果您想试验并行性,您可能想考虑使用 GNU parallel 命令.

我已经使用 100,000 个简单的 .json 文件对脚本进行了测试和基准测试 在单个目录中。在我 6 岁的计算机上,以下调用大约需要 8 分钟(挂钟时间), 其中 jq 调用大约需要 0.2 秒。

$ ./slurp.sh | jq length
100000

脚本:

#!/bin/bash
# This script slurps the contents of all the .json files in the pwd
ls | grep .json | nl | while read i f
  do
    if [ $i = 1 ] ; then
      echo "["
    else
      echo ","
    fi
      cat $f
  done
echo "]"

【讨论】:

【参考方案2】:

我不能谈论它的效率,但是对于 jq,它只是一个将所有文件一起吃掉的问题:

jq -s '.' *.json

【讨论】:

【参考方案3】:

我找到了一种非常有效的方法:

 ls |xargs -n 10000 -P 8 jq -s '.' >>../jsonparsed

这会产生 8 个并发进程,每个进程都有 10k 个参数,并写入单个 jsonfile jsonparsed

【讨论】:

你如何保证文件不会混在一起? jq 是否能够访问同一个文件而不会因为它被锁定以进行写访问而导致内容混合或出错?当 jq 也解释 json 文件的内容时,它怎么能比 cat 更快? @RedX 顺序无关紧要 也可以用cat代替jq来提高速度 @stackit - 不幸的是,使用这样的 xargs 不会达到你想要的效果。 @peak 那么我要怎么做呢?

以上是关于高效地将数百万个 JSON 文件附加到单个文件中的主要内容,如果未能解决你的问题,请参考以下文章

将数百万份文档传输到外部硬盘驱动器

哪种语言可以将数百万个脏地址稳定地处理为标准格式?

将 S3 上的数百万个小文件存档到 S3 Glacier Deep Archive

将数百万次写入文件会损坏我的硬盘吗?

如何有效地计算数百万个字符串之间的余弦相似度

数百万个 3D 点:如何找到最接近给定点的 10 个?