Python 存储/检索数据结构
我在Python中实现了一个后缀树,用于进行全文搜索,它工作得非常好。但有一个问题:索引文本可能非常大,因此我们无法在RAM中拥有整个结构 图像:单词Python 存储/检索数据结构,python,data-structures,ram,disk-io,Python,Data Structures,Ram,Disk Io,我在Python中实现了一个后缀树,用于进行全文搜索,它工作得非常好。但有一个问题:索引文本可能非常大,因此我们无法在RAM中拥有整个结构 图像:单词香蕉的后缀树(在我的场景中,想象一棵树大100000倍) 因此,我对它进行了一些研究,发现了pickle模块,这是一个很棒的Python模块,用于从文件中“加载”和“转储”对象,猜猜怎么着?它与我的数据结构配合得非常好 那么,让长话短说:在磁盘上存储和检索此结构的最佳策略是什么?我的意思是,一个解决方案可以是将每个节点存储在一个文件中,并在需要时
香蕉的后缀树(在我的场景中,想象一棵树大100000倍)
因此,我对它进行了一些研究,发现了pickle
模块,这是一个很棒的Python模块,用于从文件中“加载”和“转储”对象,猜猜怎么着?它与我的数据结构配合得非常好
那么,让长话短说:在磁盘上存储和检索此结构的最佳策略是什么?我的意思是,一个解决方案可以是将每个节点存储在一个文件中,并在需要时从磁盘加载它,但这不是最好的做法(太多的磁盘访问)
脚注:虽然我将这个问题标记为,但编程语言并不是问题的重要部分,磁盘存储/检索策略才是真正的重点。将它存储在中怎么样
SQLite:
- 支持高达2 TB的数据
- 支持SQL查询
- 是存储应用程序内数据的绝佳替代品
- 每天可支持约10万次访问(如果用于普通web应用程序)
因此,仔细研究一下这个解决方案可能会很好,因为它已被证明是在应用程序中存储数据的有效方法。也许您可以将cPickle和一个数据库结合起来,使您能够将pickle节点存储在一个类似字典的对象中,该对象将存储在文件系统上;因此,您可以稍后加载数据库,并从所需的节点获得非常好的性能
用一种非常简单的方式:
import bsddb
import cPickle
db = bsddb.btopen('/tmp/nodes.db', 'c')
def store_node(node, key, db):
db[key] = cPickle.dumps(node)
def get_node(key, db):
return cPickle.loads(db[key])
管理这样的结构的有效方法是使用内存映射文件。在文件中,不是存储节点指针的引用,而是将偏移存储到文件中。您仍然可以使用pickle
将节点数据序列化为适合存储在磁盘上的流,但您需要避免存储引用,因为pickle
模块希望一次嵌入整个树(如您所见)
使用该模块,您可以将文件映射到地址空间,并像读取一个巨大的字节序列一样读取它。操作系统负责实际读取文件,管理文件缓冲区和所有细节
您可以将第一个节点存储在文件的开头,并将该点偏移到下一个节点。读取下一个节点只是读取文件中正确的偏移量
内存映射文件的优点是它们不会一次全部加载到内存中,而只是在需要时从磁盘读取。我(在64位操作系统上)在一台只安装了4 GB RAM的机器上用30 GB的文件完成了这项工作,它工作得很好。如果pickle
已经在为您工作,您可能想看看在pickle
的基础上增加了哪些功能。查看文档,我看到了这一段,它旨在解决您的尺寸问题:
数据库在内存和存储器之间自由移动对象。如果
对象已经有一段时间没有使用了,它可能会被释放,并且
下次使用时从存储器加载的内容
请尝试使用压缩的后缀树
其主要思想是,您可以将多个节点压缩为多个字符的一个节点,从而节省额外的节点,而不是使用多个字符的节点
此处的链接()表示可以将160MB后缀树转换为33MB压缩后缀树。相当大的收获
这些压缩树用于在巨大字符串上进行遗传子字符串匹配。我以前使用后缀树时内存不足,但在压缩后,内存不足错误消失了
我希望我能找到一篇更好地解释实现的文章。()一个重要的问题是,您是想创建一次并多次使用这个结构,还是想创建它并允许更新。@GregHewgill:基本上,只需一个大文本处理来创建结构,然后使用它。顺便说一句,使用cPickle-pickle的速度要快得多。还有,为什么不使用json,而使用磁盘来对抗nosql db(我不是专家,这个主题是告诉你哪一个-但nosql是这种场景的已知解决方案-我相信比多个磁盘文件要好得多)@alonisser:nosql是一组可能的解决方案,但是,仅基于主键进行数据检索的MySQL通常与NoSQL解决方案一样高效。@Tadeck你可能是对的,因为我不是这方面的专家-而且我相信像mongoDB或couchDB这样的文档存储库使用json接口更为自然。谢谢大家的回答,在测试了您所有的选项并经过深思熟虑后,我做出了我的决定:我将使用ZODB
,这是一个非常有趣的模块,如果您喜欢这类东西,请查看它。感谢大家的回答,在测试了您所有的选项并经过深思熟虑后,我做出了我的决定:我将使用ZODB
,一个非常有趣的模块,如果你喜欢这类东西,请查看它。感谢大家的回答,在测试了你所有的选项之后,经过深思熟虑,我已经做出了我的决定:我将使用ZODB
,一个非常有趣的模块,如果你喜欢这类东西,请查看它。感谢大家的回答,在测试了您的所有选项并经过深思熟虑后,我做出了我的决定:我将使用一个非常有趣的模块ZODB
,如果您喜欢这类东西,请查看它。但是,即使树被压缩,它也必须存储在磁盘中。最终是的,取决于数据的大小。DNA序列相当长,压缩后缀为tre