我在C ++(std :: map)中使用了一个红黑树实现,但是目前,我看到我的无符号long long int索引变得越来越大,对于更大的实验。我要去700,000,000个索引,每个索引都存储一个std :: set,它包含更多的int元素(大约1-10个)。我们有128 GB RAM,但我发现我们开始缺少它;事实上,如果可能的话,我想在我的实验中,如果可能的话,我甚至要去1000,000,000个指数。
我对此进行了一些思考,并考虑将几张地图的森林放在一起。基本上,在地图达到某个大小阈值后(或者当bad_alloc开始被抛出时),将其保存到磁盘,将其从内存中清除,然后创建另一个地图并继续执行直到我获得所有索引。但是,在加载部分期间,这将是非常低效的,因为我们一次只能在RAM中保存一个映射。更糟糕的是,我们需要检查所有地图的一致性。
所以在这种情况下,我应该寻找什么样的数据结构?
答案 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
的结构,与其内容无关。使用标准库组件,不可能消除所有这些开销;关联容器的语义很好地要求每个条目的单独分配,并且使用红黑树需要添加几个指向每个条目的指针(理论上,只需要两个指针,但是如果没有高效的迭代器实现则很难父指针。)
但是,您可以通过使用如下数据结构将map
与set
组合来减少开销而不会失去功能:
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),同时通过缓存经常访问的页面等来保持良好的读/写性能。