创建可以逐步更新的有效的基于文件的索引

时间:2014-03-25 15:48:01

标签: python mongodb dictionary indexing persistence

作为一个研究项目,我目前正在Python中从头开始编写面向文档的数据库。与MongoDB一样,数据库支持在任意文档键上创建索引。这些索引当前使用两个简单的词典实现:第一个包含索引字段的(可能是散列的)值作为键,并且包含与该字段值关联的所有文档的存储键的值,这允许DB将文档定位在磁盘上。第二个字典包含其中的反转,即作为给定文档的存储键的键,并作为索引字段的(散列)值的值(这使得从索引中删除文档更有效) 。一个例子:

doc1 = {'foo' : 'bar'} # store-key : doc1
doc2 = {'foo' : 'baz'} # store-key : doc2
doc3 = {'foo' : 'bar'} # store-key : doc3

对于foo字段,这些文档的索引字典将如下所示:

foo_index = {'bar' : ['doc1','doc3'],'baz' : ['doc2']}
foo_reverse_index = {'doc1' : ['bar'],'doc2' : ['baz'], 'doc3' : ['bar']}

(请注意,反向索引也包含值列表[而不是单个值]以适应列表字段的索引,在这种情况下,列表字段的每个元素将分别包含在索引中)

在正常操作期间,索引驻留在内存中,并在每次插入/更新/删除操作后实时更新。为了保持它,它被序列化(例如作为JSON对象)并存储到磁盘,这对于索引大小高达几十个条目来说效果相当好。但是,随着数据库大小的增加,程序启动时的索引加载时间变得有问题,并且将实时中的更改提交到磁盘变得几乎不可能,因为索引的写入会产生很大的开销。

因此,我正在寻找持久性索引的实现,它允许有效的增量更新,或者换句话说,在将其保存到磁盘时不需要重写整个索引。解决这个问题的合适策略是什么?我想过使用链表来实现可以写入对象的可寻址存储空间,但我不确定这是否是正确的方法。

1 个答案:

答案 0 :(得分:1)

我的建议仅限于更新持久性索引;程序启动时的额外时间不是主要时间,也无法避免。

一种方法是为索引使用磁盘空间的预分配(也可能用于其他集合)。在预分配中,您可以定义与索引的每个条目相关联的经验大小以及磁盘上索引的总大小。例如,索引的每个条目的1024字节和总共1000个条目。 该策略允许直接访问磁盘上索引的每个条目。您只需将位置与索引一起存储在磁盘上。每次更新内存中索引的条目时,都会直接指向磁盘上的确切位置,并只重写一个条目。

如果第一个索引文件已满,只需创建第二个文件;始终为磁盘上的文件预分配空间(1024 * 1000字节)。您还应该为其他数据预分配空间,并选择使用多个固定大小的文件而不是单个大文件

如果发生索引的某些条目需要超过1024个字节,只需为更大的条目创建额外的索引文件;例如,每个条目2048个字节,总共100个条目。 最重要的是使用固定大小的索引条目进行直接访问。

我希望它有所帮助