我在为一个搜索引擎写一个倒排索引。现在,我将索引存储为字典。也就是说,每个关键字都映射到docid的字典->出现位置。在
数据模型类似于: {word:{doc_name:[位置列表]}}
在内存中构建索引工作正常,但是当我试图序列化到磁盘时,我遇到了MemoryError。我的代码是:
# Write the index out to disk
serializedIndex = open(sys.argv[3], 'wb')
cPickle.dump(index, serializedIndex, cPickle.HIGHEST_PROTOCOL)
在序列化之前,我的程序使用了大约50%的内存(1.6GB)。一旦我给cPickle打电话,我的内存使用率就飙升到80%,然后崩溃。在
为什么cPickle使用这么多内存进行序列化?有没有更好的方法来解决这个问题?在
你可以试试另一个泡菜库。也可能有一些cPickle设置可以更改。在
其他选择:把你的字典分成更小的部分,然后把每一部分都打包。当你把所有东西都装进去的时候再把它们放在一起。在
抱歉,这是模糊的,我只是在胡思乱想。我想这可能还是有帮助的,因为没有其他人回答。在
你很可能在这项工作中使用了错误的工具。如果您想持久化大量的索引数据,我强烈建议使用SQLite磁盘数据库(或者,当然,只是一个普通数据库)和一个ORM类似的SQLObject或{a2}。在
这些程序将处理一些普通的事情,如兼容性、优化格式、不同时将所有数据保存在内存中以使内存耗尽。。。在
添加:因为我一直在做一件几乎完全相同的事情,但主要是因为我是一个很好的人,这里有一个演示,它似乎能满足您的需要(它将在当前目录中创建一个SQLite文件,如果已经存在同名文件,则将其删除,因此请先将其放在空的位置):
这当然不是唯一的方法(或者一定是最好的方法)。Document表还是Word表应该与Location表分开,这取决于您的数据和典型用法。在您的例子中,“Word”表可能是一个单独的表,其中添加了一些索引和唯一性设置。在
cPickle需要使用大量额外的内存,因为它进行循环检测。如果确定数据没有循环,可以尝试使用封送处理模块
相关问题 更多 >
编程相关推荐