将巨大的(95Mb)JSON 数组拆分成更小的块?

Posted

技术标签:

【中文标题】将巨大的(95Mb)JSON 数组拆分成更小的块?【英文标题】:Split huge (95Mb) JSON array into smaller chunks? 【发布时间】:2011-10-26 13:07:18 【问题描述】:

我以 JSON 的形式从我的数据库中导出了一些数据,它本质上只是一个 [列表],其中包含一堆 (900K) objects。

现在尝试在我的生产服务器上导入它,但我有一些便宜的网络服务器。他们不喜欢我 10 分钟吃掉他们所有的资源。

我怎样才能把这个文件分割成更小的块,以便我可以一块一块地导入它?


编辑:实际上,它是一个 PostgreSQL 数据库。我愿意接受有关如何分块导出所有数据的其他建议。我的服务器上安装了 phpPgAdmin,据说它可以接受 CSV、Tabbed 和 XML 格式。


我不得不修复 phihag 的脚本:

import json
with open('fixtures/PostalCodes.json','r') as infile:
  o = json.load(infile)
  chunkSize = 50000
  for i in xrange(0, len(o), chunkSize):
    with open('fixtures/postalcodes_' + ('%02d' % (i//chunkSize)) + '.json','w') as outfile:
      json.dump(o[i:i+chunkSize], outfile)

转储:

pg_dump -U username -t table database > filename

恢复:

psql -U username < filename

(我不知道 pg_restore 到底做了什么,但它给了我错误)

这方面的教程很方便地忽略了这些信息,尤其是。 -U 选项在大多数情况下可能是必需的。是的,手册页解释了这一点,但筛选 50 个您不关心的选项总是很痛苦。


我最终接受了肯尼的建议……尽管这仍然是一个很大的痛苦。我不得不将表转储到一个文件中,压缩它,上传它,提取它,然后我尝试导入它,但是生产中的数据略有不同,并且缺少一些外键(邮政编码附加到城市)。当然,我不能只导入新城市,因为这样会引发重复键错误,而不是默默地忽略它,这会很好。所以我不得不清空那张桌子,对城市重复这个过程,却发现有别的东西与城市联系在一起,所以我也不得不清空那张桌子。重新获得城市,然后我终于可以导入我的邮政编码。到现在为止,我已经删除了一半的数据库,因为一切都与一切相关,我不得不重新创建所有条目。迷人的。还好我还没有启动这个网站。此外,“清空”或截断表似乎不会重置我想要的序列/自动增量,因为我希望有几个魔法条目 ID 为 1。所以..我必须删除或重置那些也是(我不知道如何),所以我手动编辑了那些回到 1 的 PK。

我会遇到与 phihag 的解决方案类似的问题,而且我必须一次导入 17 个文件,除非我编写了另一个导入脚本来匹配导出脚本。虽然他确实按字面意思回答了我的问题,所以谢谢。

【问题讨论】:

【参考方案1】:

我知道这是不久前的问题,但我认为这个新的解决方案很容易。

您可以使用pandas 0.21.0,它支持块大小参数作为read_json 的一部分。您可以一次加载一个块并保存 json:

import pandas as pd
chunks = pd.read_json('file.json', lines=True, chunksize = 20)
for i, c in enumerate(chunks):
    c.to_json('chunk_.json'.format(i))

【讨论】:

【参考方案2】:

我把 phihag 和 mark 的作品变成了tiny script (gist)

下面也复制了:

#!/usr/bin/env python 
# based on  http://***.com/questions/7052947/split-95mb-json-array-into-smaller-chunks
# usage: python json-split filename.json
# produces multiple filename_0.json of 1.49 MB size

import json
import sys

with open(sys.argv[1],'r') as infile:
    o = json.load(infile)
    chunkSize = 4550
    for i in xrange(0, len(o), chunkSize):
        with open(sys.argv[1] + '_' + str(i//chunkSize) + '.json', 'w') as outfile:
            json.dump(o[i:i+chunkSize], outfile)

【讨论】:

【参考方案3】:

在 Python 中:

import json
with open('file.json') as infile:
  o = json.load(infile)
  chunkSize = 1000
  for i in xrange(0, len(o), chunkSize):
    with open('file_' + str(i//chunkSize) + '.json', 'w') as outfile:
      json.dump(o[i:i+chunkSize], outfile)

【讨论】:

【参考方案4】:

假设您可以选择返回并再次导出数据...:

pg_dump - 将 PostgreSQL 数据库提取到脚本文件或其他存档文件中。

pg_restore - 从 pg_dump 创建的存档文件中恢复 PostgreSQL 数据库。

如果这没有用,那么了解您将要对输出做什么可能会很有用,以便另一个建议可以达到目标。

【讨论】:

pg_dump 会很好....但如果不是分块,恢复可能仍然会消耗太多资源。我对输出所做的只是将它导入到我的生产服务器上。 我现在正在猜测领域,但我原以为 JSON 方法中的高资源利用率与 JSON 解析有关。但正如我所说,这是一个 total 猜测。我会尝试使用 pg_dump 和 pg_restore 方法来查看发生了什么(当然是在观看资源时;)) 看起来是这样(现在可能很明显,我以前没有使用过 Postgres): --data-only 只转储数据,而不是模式(数据定义)。

以上是关于将巨大的(95Mb)JSON 数组拆分成更小的块?的主要内容,如果未能解决你的问题,请参考以下文章

将组件拆分成更小的组件,同时保持 Angular 中父组件的 `ngModel` 和 `ngModelChange` 绑定

putExtra:我应该如何处理大型数组?数据库或拆分为更小的阵列?

将数组分成更小的连续部分,使 NEO 值最大

将多个巨大的 .accdb 文件合并为一个

如何将文本文件分解成更小的块(在 Unix 上使用 C++)?

如何将 Landsat 图像裁剪成更小的块进行训练,然后在原始图像上进行预测