书架(shelve)真的很慢并且占用了很多内存,还是我做错了什么?

3
我正在尝试编写一个程序,使用shelve数据库将字母排序作为键,列表中的单词作为值。例如:
db['mnoo'] = ['moon', 'mono']

我写了一个函数,它接受一个文件名并将其加载到shelve中。第一部分,将文件转换成与shelve相同布局的字典很好用,但是shelve部分需要很长时间。

我正在尝试使用大约100k条目的字典,每个值都是列表。似乎每1000个条目需要15-20秒,每个条目需要大约1kb的空间。这正常吗?
代码如下:

def save_to_db(filename, shelve_in='anagram_db'):
    dct = anagrams_from_list(process_file(filename))

    with shelve.open(shelve_in, 'c') as db:
        for key, wordlist in dct.items():
            if not key in db:
                db[key] = wordlist
            else:
                db[key].extend(wordlist)

编辑:仅简单澄清一下,字典中的每个列表大约只有1-3个单词,不应该太大。

1个回答

5

首先,是的,shelve的默认pickle后端很慢且效率低下,您最好选择使用其他方法。

其次,当您编辑已存在的条目时,而不是将它们在内存中达到最终状态,然后只进行一次序列化,这会使情况变得更糟。

dct = anagrams_from_list(process_file(filename))
for key, wordlist in dct.items():
  content = {}
  for key, wordlist in dct.iteritems():
    if not key in content:
      content[key] = wordlist
    else:
      content[key].extend(wordlist)

for k, v in content.iteritems():
  db[k] = v

如果你需要一个高效的数据库,我建议你寻找其他选择。比如:tokyocabinet、kyotocabinet、SQLite、BDB等等,这些选项非常多。


嗯,我明白了。所以如果我已经有了数据库中的数据,并且想将其与新数据合并,那么加载所有数据,进行更改,然后保存回去会更快吗?实际上,我正在使用shelve,只是因为我是Python的新手,正在阅读《think python》,他们在某些练习中使用它。也许将来不会再使用它了 :P。 - Nescio
取决于你要改变多少数据;没有一条硬性规则。 - Charles Duffy
2
shelve 可以使用多个后端,如 gdbm 或 bdb,但只有回退的 pickle 后端速度真的很慢。 - jtaylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接