用于存储大量索引的数据结构,每个索引指向一组

时间:2013-02-18 15:15:38

标签: c++ memory-management data-structures map

我在C ++(std :: map)中使用了一个红黑树实现,但是目前,我看到我的无符号long long int索引变得越来越大,对于更大的实验。我要去700,000,000个索引,每个索引都存储一个std :: set,它包含更多的int元素(大约1-10个)。我们有128 GB RAM,但我发现我们开始缺少它;事实上,如果可能的话,我想在我的实验中,如果可能的话,我甚至要去1000,000,000个指数。

我对此进行了一些思考,并考虑将几张地图的森林放在一起。基本上,在地图达到某个大小阈值后(或者当bad_alloc开始被抛出时),将其保存到磁盘,将其从内存中清除,然后创建另一个地图并继续执行直到我获得所有索引。但是,在加载部分期间,这将是非常低效的,因为我们一次只能在RAM中保存一个映射。更糟糕的是,我们需要检查所有地图的一致性。

所以在这种情况下,我应该寻找什么样的数据结构?

3 个答案:

答案 0 :(得分:2)

看起来是时候切换到B树(可能是B +或B *) - 这种结构在数据库中用来管理索引。看看here - 这是替换std-like关联容器w / btree里面...但是btree可以用来将索引保存在内存和磁盘上......

答案 1 :(得分:2)

根据你的描述,我认为你有这个:

typedef std::map<long long, std::set<int>> MyMap;

map非常大,个别集非常小。这里有几个开销来源:

  • map中的各个条目,每个条目都是单独的分配;
  • set s中的各个条目,同上;
  • 描述每个set的结构,与其内容无关。

使用标准库组件,不可能消除所有这些开销;关联容器的语义很好地要求每个条目的单独分配,并且使用红黑树需要添加几个指向每个条目的指针(理论上,只需要两个指针,但是如果没有高效的迭代器实现则很难父指针。)

但是,您可以通过使用如下数据结构将mapset组合来减少开销而不会失去功能:

typedef std::set<std::pair<long long, int>> MyMap;

您仍然可以回答所有相同的查询,但其中一些查询稍微不方便。请记住,std::pair的默认比较器按字典顺序排序,因此具有相同first值的所有元素将是连续的。例如,您可以使用以下命令查询给定索引是否与其关联的任何int

it = theMap.lower_bound(std::make_pair(index, INT_MIN));
if (it != theMap.end() && it->first == index) {
  // there is at least one int associated with index
}

lower_bound的同一调用会给你一个int s associate with the key, while a call to upper_bound的开始迭代器(std :: make_pair(key,INT_MAX))`会给你相应的结束迭代器,所以你可以轻松迭代与给定密钥关联的所有值。

除非平均设置的大小非常小,否则仍然可能不足以存储7亿个带有128GB的关联整数的索引。下一步必须是某种形式的b树,它不在标准库中。 B树通过将多个条目组合到单个集群中来避免单独的条目开销;这应该足以满足您的需求。

答案 2 :(得分:1)

对于如此大规模的数据集,您应该使用正确的database server,例如 SQL服务器。这些服务器旨在使用缓存的大型数据集。 SQL服务器将数据保存到永久性缓存(如HDD),同时通过缓存经常访问的页面等来保持良好的读/写性能。