c++ - 如何有效地解析 C++ 中的大数据 json 文件(wikidata)?

标签 c++ json bigdata rapidjson wikidata

我有一个大约 36 GB 的 json 文件(来自维基数据),我想更有效地访问它。目前我在 C++ 中使用 rapidjsons SAX 风格的 API——但是解析整个文件在我的机器上花费了大约 7415200 毫秒(=120 分钟)。我想根据 json 对象中的两个主键('name' 或 'entity-key' -> 即 'Stack Overflow' 或 'Q549037')之一访问此文件中的 json 对象。这意味着我必须在最坏的情况下解析当前的整个文件。

所以我想到了两种方法:

  • 将大文件拆分为数十亿个小文件 - 文件名指示名称/实体键(即 Q549037.json/Stack_Overflow.json 或 Q549037#Stack_Overflow.json)-> 不确定存储中的过载
  • 构建某种从主键到文件中 ftell() 位置的索引。建立索引大约需要 120 分钟(就像现在解析一样),但访问速度应该会更快
    • 即使用类似两个 std::unorderedmap 的东西(可能再次遇到内存问题)
    • 索引文件 - 创建两个文件:一个包含按名称排序的条目,另一个按实体键排序(创建这些文件可能需要更长的时间,因为排序)

解决此类问题的最佳做法是什么? 我应该遵循哪种方法?还有其他想法吗?

最佳答案

我认为性能问题不是由于解析造成的。使用 RapidJSON 的 SAX API 应该已经提供了良好的性能和内存友好。如果您需要访问 JSON 中的每个值,这可能已经是最好的解决方案。

但是,从问题描述来看,一次读取所有值似乎不是您的要求。您想要读取特定标准(例如,通过主键)的一些(可能是少量)值。然后读取/解析所有内容不适合这种情况。

您将需要一些索引机制。用文件位置做这件事是可能的。如果这些位置的数据也是有效的 JSON,您可以查找并将其流式传输到 RapidJSON 以解析该 JSON 值(通过 kParseStopWhenDoneFlag 解析完整的 JSON 后,RapidJSON 可以停止解析)。

其他选项是将 JSON 转换为某种数据库,SQL 数据库、键值数据库或自定义数据库。借助提供的索引工具,您可以快速查询数据。这可能需要很长时间才能转换,但对于以后的检索具有良好的性能。

请注意,JSON 是一种交换格式。它不是为大数据的快速个人查询而设计的。


更新:最近发现有个项目semi-index可能适合您的需求。

关于c++ - 如何有效地解析 C++ 中的大数据 json 文件(wikidata)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28391434/

相关文章:

mysql - 如何比较hive和mysql的性能

sql - 如何让 Spark 处理更大的数据集?

c++ - C++如何求出一个数的位数?

java - Json解析重音字符

c++ - 如何在 Linux 上使用 QProcessEnvironment 设置代理地址?

json - 别名时更新ElasticSearch interval_refresh

javascript - 默认响应和实际响应之间的差异和交换 JSON 值

c++ - 将 900 MB .csv 转换为 ROOT (CERN) TTree

c++ - NetBeans 在编译 C++ 项目时无法执行 Perl 脚本

java - c++ 套接字客户端继续从 Java 服务器接收某些内容,即使输出流已关闭