使用python pickle加载大字典
我有一个嵌套python字典形式的完整倒排索引。其结构是:
{word : { doc_name : [location_list] } }
例如,让字典称为索引,然后对于单词“spam”,条目看起来像:
{ spam : { doc1.txt : [102,300,399], doc5.txt : [200,587] } }
我使用这个结构,因为python dict非常优化,它使编程更容易。
对于任何“垃圾邮件”这个词,包含它的文件可以通过以下方式给出:
index['spam'].keys()
并通过以下方式发布文档doc1的列表:
index['spam']['doc1']
目前我正在使用cPickle来存储和加载这本字典。但是腌制文件大约是380 MB并且需要很长时间才能加载 - 112秒(大约我使用time.time()定时)并且内存使用量达到1.2 GB(Gnome系统监视器)。一旦它加载,它的罚款。我有4GB内存。
len(index.keys())
给出229758
码
import cPickle as pickle
f = open('full_index','rb')
print 'Loading index... please wait...'
index = pickle.load(f) # This takes ages
print 'Index loaded. You may now proceed to search'
如何让它加载更快?我只需要在应用程序启动时加载一次。之后,访问时间对于响应查询很重要。
我应该切换到像SQLite这样的数据库并在其键上创建索引吗?如果是,我如何存储值以具有等效模式,这使得检索变得容易。还有什么我应该研究的吗?
附录
使用蒂姆的答案pickle.dump(index, file, -1)
腌制文件相当小 - 大约237 MB(需要300秒才能转储)......现在需要花费一半的时间来加载(61秒......而不是之前的112秒....时间。时间())
但是我应该迁移到数据库以获得可伸缩性吗?
至于现在,我正在接受蒂姆的回答。
PS:我不想使用Lucene或Xapian ......
这个问题涉及存储倒排索引。我不得不问一个新问题,因为我无法删除前一个问题。
没有找到相关结果
已邀请:
5 个回复
遣莫捅炭
/
时尝试使用protocol参数。从
: Pickler(文件,协议= 0) - 创建一个pickler。 这需要一个类似文件的对象来编写pickle数据流。 可选的proto参数告诉pickler使用给定的 协议;支持的协议是0,1,2。默认 协议为0,向后兼容。 (协议0是 只能写入文本中打开的文件的协议 模式并成功回读。使用更高的协议时 小于0,确保文件以二进制模式打开,两者都是 酸洗和去除。) 协议1比协议0更有效;协议2是 比协议1更有效。 指定否定协议版本会选择最高版本 协议版本支持。协议使用的越高, 最近需要读取pickle的Python版本 产生的。 file参数必须具有接受单个的write()方法 字符串参数。因此它可以是一个打开的文件对象,一个StringIO 对象或满足此接口的任何其他自定义对象。 转换JSON或YAML可能需要比大多数时间的酸洗更长的时间 - pickle存储本机Python类型。
扭湘阀柿蹄
。
提供了用于写入数据库的字典抽象,包括将文件系统视为数据库(即将整个字典写入单个文件,或将每个条目写入其自己的文件)。对于大数据,我经常选择将字典表示为我的文件系统上的目录,并将每个条目都作为文件。
还提供缓存算法,因此如果您使用字典的文件系统后端,则可以通过利用内存缓存来避免一些速度损失。
还有其他标志,如
和
,可用于自定义数据的存储方式(例如压缩级别,内存映射模式等)。 使用(MySQL等)数据库作为后端而不是文件系统同样容易(相同的界面)。您还可以关闭内存缓存,因此只需设置
,每次读/写都会直接进入存档。 通过构建自定义
,
可以自定义编码。
还提供了许多缓存算法(如
,
,
等),以帮助您管理内存缓存,并将使用算法进行转储并加载到归档后端。 您可以使用标志
完全关闭内存缓存,并直接读写磁盘或数据库。如果您的条目足够大,您可以选择写入磁盘,将每个条目放在其自己的文件中。这是两个例子。
然而,虽然这应该会大大减少加载时间,但它可能会使整体执行速度降低一些......通常最好指定内存缓存中保留的最大数量并选择一个好的缓存算法。您必须使用它才能获得满足您需求的正确平衡。 在这里获取
:https://github.com/uqfoundation
物崎巩
和
。这会导致导入加速版本的负担,并在这些模块的每个用户上回退到纯Python版本。在Python 3.0中,加速版本被认为是纯Python版本的实现细节。用户应始终导入标准版本,该版本尝试导入加速版本并回退到纯Python版本。 pickle / cPickle对接受了这种治疗。 协议版本0是原始的“人类可读”协议,并且向后兼容早期版本的Python。 协议版本1是旧的二进制格式,它也与早期版本的Python兼容。 在Python 2.3中引入了协议版本2。它提供了更有效的新式类型的酸洗。有关协议2带来的改进的信息,请参阅PEP 307。 在Python 3.0中添加了协议版本3。它具有对字节对象的显式支持,并且不能被Python 2.x打开。这是默认协议,需要与其他Python 3版本兼容时的推荐协议。 在Python 3.4中添加了协议版本4。它增加了对非常大的对象的支持,挑选更多种类的对象,以及一些数据格式优化。有关协议4带来的改进的信息,请参阅PEP 3154。 如果您的字典很大并且只应与Python 3.4或更高版本兼容,请使用:
要么:
也就是说,在2010年,
模块的编码速度提高了25倍,解码简单类型的速度提高了15倍。我的2014年基准测试表示
>
>
,但
与特定的Python版本相结合。
屑凉赦
模块本地支持来自Python 2.6的JSON,并且YAML还有第三方模块。 您也可以尝试
模块。
视蕉梁拌客