python - 创建一个可以增量更新的高效的基于文件的索引

标签 python mongodb dictionary indexing persistence

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

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 对象)并存储到磁盘,这对于索引大小高达几个 100k 条目的情况相当有效。然而,随着数据库大小的增长,程序启动时的索引加载时间变得有问题,并且实时将更改提交到磁盘变得几乎不可能,因为写入索引会产生很大的开销。

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

最佳答案

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

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

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

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

希望对你有帮助

关于python - 创建一个可以增量更新的高效的基于文件的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22639621/

相关文章:

python - 提高Pytesseract阅读文本的可靠性

在字典中设置值的pythonic方式

javascript - mongodb函数currentOp()的返回记录放在哪里?

mongodb - 替换为 mongodb 中的 (mysql) 等价物

python - 从多个 celery worker 登录到一个文件安全吗?

python - 在正则表达式匹配之间插入空格

Java比较两个csv文件

python - 在 python 中映射 csv

java - 可以将 mongodb writeconcern 设置为仅忽略重复键错误吗?

c# - Dictionary ToList 序列化问题