搁置对于大型词典来说太慢了,我该怎么做才能提高性能?

时间:2010-08-19 19:04:52

标签: python database performance persistence shelve

我正在使用python存储一个表,我需要持久性。

基本上我将表作为字典字符串存储到数字中。整个存储与搁置

self.DB=shelve.open("%s%sMoleculeLibrary.shelve"%(directory,os.sep),writeback=True) 

我使用writebackTrue,因为我发现系统往往不稳定,如果我不这样做。

计算完成后,系统需要关闭数据库并将其存储回来。现在数据库(表格)大约是540MB,而且需要很长时间。桌子增长到大约500MB后,时间爆炸了。但我需要一张更大的桌子。事实上我需要其中两个。

我可能正在使用错误的持久性形式。我该怎么做才能提高绩效?

4 个答案:

答案 0 :(得分:13)

为了存储string : number键值对的大型字典,我建议使用JSON本地存储解决方案,例如MongoDB。它有一个很棒的Python API,Pymongo。 MongoDB本身是轻量级的,速度非常快,json对象本身就是Python中的字典。这意味着您可以使用string密钥作为对象ID,允许压缩存储和快速查找。

作为代码容易实现的示例,请参阅以下内容:

d = {'string1' : 1, 'string2' : 2, 'string3' : 3}
from pymongo import Connection
conn = Connection()
db = conn['example-database']
collection = db['example-collection']
for string, num in d.items():
    collection.save({'_id' : string, 'value' : num})
# testing
newD = {}
for obj in collection.find():
    newD[obj['_id']] = obj['value']
print newD
# output is: {u'string2': 2, u'string3': 3, u'string1': 1}

你只需要从unicode转换回来,这是微不足道的。

答案 1 :(得分:9)

根据我的经验,我建议使用Python附带的SQLite3。它适用于较大的数据库和关键数字。数以百万计的密钥和千兆字节的数据不是问题。 Shelve在这一点上完全被浪费了。单独的db-process也没有用,它只需要更多的上下文交换。在我的测试中,我发现在本地处理更大的数据集时,SQLite3是首选的选项。运行本地数据库引擎(如mongo,mysql或postgresql)不会提供任何其他值,也会更慢。

答案 2 :(得分:1)

多大?访问模式有哪些?你需要做什么样的计算呢?

请记住,如果无论如何都不能将表保留在内存中,您将会有一些性能限制。

您可能希望查看SQLAlchemy,或直接使用类似bsddb的内容,但这两种方法都会牺牲代码的简单性。但是,使用SQL,您可以根据工作负载将部分工作卸载到数据库层。

答案 3 :(得分:1)

我认为您的问题是由于您使用writeback=Truedocumentation说(重点是我的):

  

由于Python语义,架子无法知道何时可变   持久字典条目被修改。默认情况下修改对象   只有在分配到货架时才会写入(参见示例)。如果   可选的writeback参数设置为True,访问的所有条目都是   也缓存在内存中,并写回sync()和close();这个   可以使持久化中的可变条目变得更容易   字典,但是,如果访问了很多条目,它可能会消耗很多   缓存的内存量,可以进行关闭操作   因为所有被访问的条目都被写回来非常慢(没有办法   确定哪些访问的条目是可变的,哪些是可变的   实际上是变异的。)

您可以避免使用writeback=True并确保数据只写入一次(您必须注意后续修改将会丢失)。

如果您认为这不是正确的存储选项(很难说不知道数据是如何构建的),我建议使用sqlite3,它集成在python中(因此非常便携)并且具有非常好的性能。它比简单的键值存储更复杂。

查看替代品的其他答案。