我正在使用python存储一个表,我需要持久性。
基本上我将表作为字典字符串存储到数字中。整个存储与搁置
self.DB=shelve.open("%s%sMoleculeLibrary.shelve"%(directory,os.sep),writeback=True)
我使用writeback
到True
,因为我发现系统往往不稳定,如果我不这样做。
计算完成后,系统需要关闭数据库并将其存储回来。现在数据库(表格)大约是540MB,而且需要很长时间。桌子增长到大约500MB后,时间爆炸了。但我需要一张更大的桌子。事实上我需要其中两个。
我可能正在使用错误的持久性形式。我该怎么做才能提高绩效?
答案 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=True
。 documentation说(重点是我的):
由于Python语义,架子无法知道何时可变 持久字典条目被修改。默认情况下修改对象 只有在分配到货架时才会写入(参见示例)。如果 可选的writeback参数设置为True,访问的所有条目都是 也缓存在内存中,并写回sync()和close();这个 可以使持久化中的可变条目变得更容易 字典,但是,如果访问了很多条目,它可能会消耗很多 缓存的内存量,可以进行关闭操作 因为所有被访问的条目都被写回来非常慢(没有办法 确定哪些访问的条目是可变的,哪些是可变的 实际上是变异的。)
您可以避免使用writeback=True
并确保数据只写入一次(您必须注意后续修改将会丢失)。
如果您认为这不是正确的存储选项(很难说不知道数据是如何构建的),我建议使用sqlite3,它集成在python中(因此非常便携)并且具有非常好的性能。它比简单的键值存储更复杂。
查看替代品的其他答案。