我有一个大词典(1mil键)的形式:
{
key1: {
file1: [number_list1],
file7: [number_list2],
file10: [number_list3],
...
}
key2: {
file1: [number_list4],
file5: [number_list5],
file2: [number_list6],
...
}
...
...
}
由于各种限制,在构建之后我无法将其保留在内存中,并且必须以其腌制形式将其转储到磁盘上。但是,我仍然希望从磁盘快速查找任何一个密钥。
我的想法是把大字体分成更小的块(0.5-1MB的球场)。这需要一个额外的密钥:块映射,但允许我在查找期间仅加载必要的块。我提出了以下算法:
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
为1mil密钥表执行0.4s查询时间,我怀疑mongo会更快。对我的用例来说,开销太大了。我想我将继续我自己的分区数据库实现。