存储巨大的std :: map,主要是在磁盘上

时间:2008-12-30 01:42:38

标签: c++ data-structures

我有一个可能产生大量数据的C ++程序 - 数十亿个不同大小的二进制记录,最可能少于256个字节,但有几个延伸到几K.大多数记录很少会程序在创建后查看,但有些会定期访问和修改。没有办法告诉他们什么时候被创造出来。

考虑到数据量,我无法将其全部存储在内存中。但由于数据只需要通过其编号(64位整数)进行索引和访问,因此我不希望需要完整数据库程序的开销。理想情况下,我希望将其视为std::map,其数据存储在磁盘上直到请求。

是否有一个已经编写的库可以完成我正在寻找的工作,或者我是否需要自己编写?

编辑:经过一番思考后,我意识到Rob Walker的回答有一个有效的观点:我很难从家庭酿造课程中获得与我从中获得的同类数据完整性。一个真正的数据库。

虽然BerkeleyDB(正如RHM所建议的)看起来像我们正在寻找的那样,但双重许可是我们不想处理的头痛问题。当我们完成代码并且可以证明它会从BerkeleyDB(它可能会)中获益时,我们将重新审视这个问题。

我确实看过Ferruccio对stxxl的建议,但是我无法告诉它如何处理被中断和重启的程序(可能有更改)。有了这么多的数据,我不想废弃它已经完成的东西并且每次重新开始,如果可以保存一些数据。

所以我们决定使用SQLite数据库,至少在初始开发时使用。感谢所有回答或投票的人。

8 个答案:

答案 0 :(得分:7)

看看STXXL

stxxl::map<>看起来完全符合您的需要。

答案 1 :(得分:5)

我怀疑您会找到一个完全符合您要求的库,因此您必须确定哪些'功能'对您来说真正重要,然后确定现有数据库解决方案是否足够接近。

数十亿条记录在任何范围内都是一个庞大的数据集。记录的生成率是多少?他们坚持多久了?访问模式是否随时间而变化?

更新是否始终与原始数据量相同?

我建议明确证明数据库解决方案在开始自己开发之前不会起作用,特别是如果数据的完整性是最重要的(通常是......)可靠地维护磁盘上的数据量肯定是一个挑战。更改数据时是否需要任何类型的事务语义?客户端是多线程的吗?

答案 2 :(得分:4)

BerkleyDB可能对你有好处。它基于字符串而不是数字进行索引,但您可以将数字格式化为十六进制。假设基本上与基于磁盘的键/值查找一样快。

答案 3 :(得分:2)

我使用了Gigabase http://www.garret.ru/gigabase.html,在几个项目中,它有一个简洁的C ++接口,我已经处理了数百万条没有问题的记录,它支持回滚。它有麻省理工学院的许可证,作者也很快回答问题和修复错误。

答案 4 :(得分:2)

您可以使用SQLLite,这是一个发布到公共域的开源数据库。

http://www.sqlite.org/

我会引用他们的网页:

  

SQLite是一个软件库,它实现了一个独立的,无服务器,零配置的事务SQL数据库引擎。 SQLite是世界上部署最广泛的SQL数据库引擎。 SQLite的源代码位于公共领域。

  

SQLite的持续开发和维护部分由SQLite Consortium成员赞助,包括:Adobe,Symbian,Bloomberg,Mozilla

如果你需要一个轻量级数据库,这可能只是它

答案 5 :(得分:1)

你可能不得不自己动手。我可能会把它放在几个mysql表中并且懒得加载一个固定大小的地图(lru)。如果你真的不想避免数据库,请放置&lt; 256或固定记录随机访问文件中的任何长度记录,并将较大的记录存储为单个文件。

答案 6 :(得分:0)

根据您需要的性能特征,答案是不同的。但是考虑到问题描述中的信息,我认为数据库过度,实际上可能适得其反。

将每个条目保存为名称为其密钥的文件(即,密钥“1”对应于磁盘上的文件“1.dat”),这是一个简单的解决方案,可避免出现多个问题。假设您可以控制软件将运行的文件系统,如果您选择具有良好完整性的文件系统,则您的数据应该具有良好的完整性。您可以编写大量代码将条目分组在一个文件中,然后不得不担心调整大小,或者您可以让文件系统为您处理(它旨在处理更改大小的文件)。您可能担心以线程安全的方式将它们写入该文件,或者您可以让文件系统为您处理(文件系统被设计为具有不同的进程同时写入不同的文件)。您可能会担心文件被部分保存到磁盘并编写代码来检查它,或者您可以让文件系统为您处理(日志和原子写入)。您可能会担心将更改的写入一起调度以获得速度,或者您可以让文件系统为您处理此问题(写入缓存)。

基本上,一个好的文件系统和操作系统应该为你处理所有这些,并且在它之上添加一个试图复制所有这些功能的数据库只会产生更多的复杂性和更多的bug。如果您需要按不同的字段索引数据,那么数据库可能有意义,但在您的描述中,您说您每次只需要使用相同的整数键索引数据。

答案 7 :(得分:0)

我同意其他人的看法,BerkeleyDB,sqlite或gigabase应该是很好的解决方案。

编写自己的解决方案也不应该太难。

我有一个简单的解决方案,但有三个先决条件:

  1. 您至少可以在内存中保留std::vector<int64>numkey元素。
  2. 您的钥匙是或可以连续。
  3. 写入文件后,每个数据记录大小都有一个固定的maxsize,即其大小不能增加。
  4. 如果满足这些先决条件,直接的解决方案是将每个键(int64)的文件位置(int64)存储在内存中的向量中。对于查找,只需从向量seek检索文件位置到该位置,在那里找到记录大小作为其第一个条目,并读取size个字节。