【发布时间】:2015-04-08 02:38:41
【问题描述】:
我有一个大约 36 GB 的 json 文件(来自 wikidata),我想更有效地访问它。目前我在 C++ 中使用 rapidjsons SAX 风格的 API——但解析整个文件在我的机器上需要大约 7415200 毫秒(=120 分钟)。我想根据 json 对象内的两个主键(“名称”或“实体键”-> 即“堆栈溢出”或“Q549037”)之一访问此文件中的 json 对象。这意味着我必须在最坏的情况下解析当前的整个文件。
所以我想到了两种方法:
- 将大文件拆分为数十亿个小文件 - 文件名指示名称/实体键(即 Q549037.json / Stack_Overflow.json 或 Q549037#Stack_Overflow.json) -> 不确定存储中的过载
- 从主键到文件中的
ftell()位置建立某种索引。建立索引大约需要 120 分钟(就像现在解析一样),但访问应该更快- 即使用两个
std::unorderedmap之类的东西(可能会再次遇到内存问题) - 索引文件 - 创建两个文件:一个具有按名称排序的条目,另一个按实体键排序(创建这些文件可能需要更长的时间,因为排序)
- 即使用两个
解决此类问题的最佳做法是什么? 我应该遵循哪种方法?还有其他想法吗?
【问题讨论】:
-
如果您决定编写自己的想法,请考虑使用正确的解析树而不是无序映射。
boost::intrusive可能会有所帮助。 -
您还可以考虑使用 MongoDB 或其他一些 NoSQL 数据库来存储 JSON 数据。据我了解,这是 NoSQL 数据库的(初始)点。
-
我刚刚意识到您的吞吐量只有大约 5MB/s。在我的机器上,内存中的 SAX 解析大约是 300MB/s。 DOM 约为 200MB/s。所以对于大文件,它应该是 I/O 绑定的。我怀疑出了什么问题。你用的是github的最新版本吗?
-
@MiloYip 是的,没错 - 300 MB/s 应该只需要大约 2 分钟:我想我必须再做一些检查,为什么它慢到 5 MB/s我的电脑。
标签: c++ json bigdata rapidjson wikidata