修改ZODB中的数据

时间:2012-07-04 21:20:33

标签: python zodb

根据here给出的建议,我使用ZODB存储了我的数据,由以下代码创建:

# structure of the data [around 3.5 GB on disk]
bTree_container = {key1:[ [2,.44,0], [1,.23,0], [4,.21,0] ...[10,000th element] ], key2:[ [3,.77,0], [1,.22,0], [6,.98,0] ..[10,000th element] ] ..10,000th key:[[5,.66,0], [2,.32,0], [8,.66,0] ..[10,000th element]]}

# Code used to build the above mentioned data set
for Gnodes in G.nodes():      # Gnodes iterates over 10000 values 
Gvalue = someoperation(Gnodes)
    for i,Hnodes in enumerate(H.nodes()):  # Hnodes iterates over 10000 values 
        Hvalue =someoperation(Hnodes)
        score = SomeOperation on (Gvalue,Hvalue)
        btree_container.setdefault(Gnodes, PersistentList()).append([Hnodes, score, 0]) # build a list corresponding to every value of Gnode (key)
        if i%5000 == 0       # save the data temporarily to disk.
           transaction.savepoint(True)
transaction.commit()         # Flush all the data to disk

现在,我想(在一个单独的模块中)(1)修改存储的数据和(2)对它进行排序。以下是我正在使用的代码:

storage = FileStorage('Data.fs')
db = DB(storage)
connection = db.open()
root = connection.root()
sim_sorted = root[0]

# substitute the last element in every list of every key (indicated by 0 above) by 1
# This code exhausts all the memory, never get to the 2nd part i.e. the sorting 
for x in sim_sorted.iterkeys():
    for i,y in enumerate(sim_sorted[x]):
        y[3] = 1
        if i%5000 ==0
            transaction.savepoint()

# Sort all the lists associated with every key in he reverse order using middle element as key   
[sim_sorted[keys].sort(key = lambda x:(-x[1])) for keys in sim_sorted.iterkeys()]

然而,用于编辑值的代码占用了所有内存(从未进行排序)。我不确定这是如何工作的,但我觉得我的代码存在严重错误,ZODB将所有东西都拉入内存,从而解决问题。实现所需效果的正确方法是什么,即在ZODB中替换和排序存储的元素而不会遇到内存问题?代码也很慢,建议加快它?

[注意:我没有必要将这些更改写回数据库]

EDIT 通过在内部循环之后添加命令connection.cacheMinimize(),内存使用似乎有一点改进,但​​是在一段时间之后整个RAM被消耗了,这让我感到困惑。

1 个答案:

答案 0 :(得分:1)

你确定这不是排序会扼杀你的记忆吗?

请注意,我希望每个PersistentList都必须适合内存;它是一个持久性记录,因此它将作为一个整体加载进行访问。

我修改你的代码就像这样运行,看看会发生什么:

for x in sim_sorted.iterkeys():
    for y in sim_sorted[x]:
        y[3] = 1
    sim_sorted[x].sort(key=lambda y: -y[1])
    transaction.savepoint()

现在你一次处理整个列表并对其进行排序;毕竟,它已经加载到内存中。处理完毕后,告诉ZODB您已完成此阶段,整个更改后的列表将刷新到临时存储。只有中途完成时,没有什么可以冲洗的。

如果这仍然不适合您的内存,您需要重新考虑您的数据结构并将大型列表拆分为较小的持久性记录,以便您可以一次处理它的大块而不加载整个事物在一个。