【发布时间】:2017-07-16 15:15:18
【问题描述】:
我有一本大字典(100 万键),格式如下:
{
key1: {
file1: [number_list1],
file7: [number_list2],
file10: [number_list3],
...
}
key2: {
file1: [number_list4],
file5: [number_list5],
file2: [number_list6],
...
}
...
...
}
由于各种限制,在构建它之后,我无法将它保存在内存中,而不得不以腌制形式将其转储到磁盘上。但是,我仍然希望从磁盘快速查找任何一个键。
我的想法是将大字典分成更小的块(大约 0.5-1MB)。这需要一个额外的 key:chunk 映射,但允许我在查找期间只加载必要的块。我想出了以下算法:
def split_to_pages(self, big_dict):
page_buffer = defaultdict(lambda: defaultdict(list))
page_size = 0
page_number = 0
symbol2page = {}
for symbol, files in big_dict.items():
page_buffer[symbol] = files
symbol2page[symbol] = page_number
page_size += deep_sizeof_bytes(files)
if page_size > max_page_size:
save_page_to_file(page_number, page_buffer)
page_buffer.clear()
page_size = 0
page_number += 1
if page_size > 0:
save_page_to_file(page_number, page_buffer)
此解决方案对于静态字典表现良好。但是,由于它代表一个动态实体,因此很可能在操作期间将新键引入或从 dict 中删除。为了反映这种变化,我的解决方案需要从头开始对整个 dict 进行分区。有没有更好的方法来处理这种情况?我有一种感觉,这是一个我不知道的常见问题,并且已经针对此问题提出了更好的解决方案。
编辑:
我尝试了shelve,对于一个小型数据库(2k 键)大约需要 0.5 秒的键查找时间,这非常慢。我上面描述的半生不熟的分页算法大约是 0.01 秒。
sqlite3 为 100 万个键表做了 0.4 秒的查找时间,我怀疑 mongo 会更快。我的用例开销太大。我想我会继续我自己的分区数据库实现。
【问题讨论】:
-
我猜这就是发明数据库的原因?
-
同意。您可以尝试使用
redis、mongoDB或其他一些 NoSQL 存储。 -
你可以试一试
tinydb。不知道它可以处理多少数据。 -
我知道数据库,我认为我不必走那条路,因为这对我的应用程序来说有点矫枉过正。我想别无选择。
-
在使用数据库之前,先试试
shelve模块
标签: python dictionary