计算在ZODB中保存的BTree的len()需要很长时间

时间:2016-01-02 22:42:16

标签: python zodb

我使用ZODB和BTree来存储大量数据(数百万个密钥)。我想获得根词典中的确切条目数(BTree)。正如我注意到的,len()调用.keys()的结果需要很长时间(至少几十分钟,老实说,当数据集变大时,我从未等待它结束)。

import ZODB
from BTrees.OOBTree import BTree

connection = ZODB.connection('database.fs')
dbroot = connection.root()

if not hasattr(dbroot, 'dictionary'):
    dbroot.dictionary = BTree()

# much data is added and transactions are commited

number_of_items = len(dbroot.dictionary.keys()) # takes very long time

我定期打包数据库。

我认为这与问题无关,但dbroot.dictionary包含其他BTree作为值。

1 个答案:

答案 0 :(得分:4)

您正在调用.keys()方法,该方法必须加载并生成所有键的完整列表。 需要花费很多时间。

您可以询问BTree 本身的长度

number_of_items = len(dbroot.dictionary)

这仍然需要load all the buckets themselves(键块)来询问每个的长度,所以这仍然需要加载大量数据,而不是生成列表。

我们总是避免试图获得直接的长度; Btree.Length object更适合于“手动”跟踪长度。该对象完全是ZODB冲突解决方案。每次向dbroot.dictionary添加元素时,都会向BTree.Length对象添加一个计数并让它保持计数:

from BTrees.OOBTree import BTree
from BTrees.Length import Length

if not hasattr(dbroot, 'dictionary'):
    dbroot.dictionary = BTree()
    dbroot.dict_length = Length()

# add objects into the dictionary? Add to the length as well:
for i in range(count):
    dbroot.dictionary[keys[i]] = value[i]
dbroot.dict_length.change(count)

然后通过调用对象读出长度:

length = dbroot.dict_length()