2

我有一些数据存储在我想要处理的数据库中。数据库访问非常缓慢,因此我决定在进行任何处理之前将所有数据加载到字典中。但是,由于存储的数据量很大,我遇到了内存不足错误(我看到使用了超过 2 个演出)。所以我决定使用磁盘数据结构,并发现使用搁置是一种选择。这就是我所做的(伪python代码)

def loadData():
    if (#dict exists on disk):
        d = shelve.open(name)
        return d
    else:
        d = shelve.open(name, writeback=True)
        #access DB and write data to dict
        # d[key] = value 
        # or for mutable values
        # oldValue = d[key]
        # newValue = f(oldValue)
        # d[key] = newValue 
        d.close()
        d = shelve.open(name, writeback=True)
        return d

我有一些问题,

1) 我真的需要 writeBack=True 吗?它有什么作用?

2) 我仍然遇到 OutofMemory 异常,因为我无法控制数据何时写入磁盘。我怎么做?我尝试每隔几次迭代执行一次 sync() ,但这也无济于事。

谢谢!

4

2 回答 2

10

writeback=True强制货架将任何已获取的项目保留在内存中,并在货架关闭时将它们写回。因此,它消耗更多的内存,并减慢关闭速度。

该参数的优点是,有了它,您不需要在注释中显示的扭曲代码,用于其 mutator 是一种方法的可变项 - 只需

shelf['foobar'].append(23)

工作(如果shelf在启用写回的情况下打开),假设 key 上的项目'foobar'当然是一个列表,而如果在没有写回的情况下打开它,它将默默地是一个无操作(保持磁盘上的项目不变)shelf- 在后一种情况下你实际上确实需要编码

thelist = shelf['foobar']
thelist.append(23)
shekf['foobar'] = thelist

本着你评论的精神——这在风格上有点令人失望。

但是,由于您遇到内存问题,我绝对建议不要使用这个可疑的写回选项。我认为我可以称其为“可疑”,因为我是第一个提出并第一个实施它的人,但那是很多年前的事了,而且我基本上已经后悔这样做了——它比它更普遍地混淆(正如你的 Q 所证明的那样)允许优雅和方便地移动最初编写为使用 dicts 的代码(它将使用第一个习语,而不是第二个习语,因此需要重写才能在没有回溯的情况下与货架一起使用)。啊,好吧,对不起,当时这确实是个好主意。

于 2010-02-04T04:03:09.097 回答
0

在这里使用该sqlite3模块可能是您的最佳选择。无论如何,您也许可以完全在内存中使用 sqlite,因为它的内存占用可能比使用 python 对象要小一些。它通常是比使用shelve任何方式更好的选择;shelve在下面使用pickle,这很少是你想要的。

地狱,您可以将整个现有数据库转换为 sqlite 数据库。sqlite 又好又快。

于 2010-02-04T03:24:50.667 回答