如何有效地解析C++中的bigdata json文件(wikidata)?

Con*_*tin 8 c++ json bigdata rapidjson wikidata

我有一个大约36 GB的json文件(来自wikidata),我希望更有效地访问它.目前我在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(可能再次遇到内存问题)
    • 索引文件 - 创建两个文件:一个按名称排序的条目和一个按实体键排序的文件(由于排序,创建这些文件可能需要更长的时间)

这样的问题最好的做法是什么?我应该遵循哪种方法?还有其他想法吗?

Mil*_*Yip 3

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

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

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

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

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


更新:最近我发现有一个项目半索引可能适合你的需求。