Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 存储/检索数据结构_Python_Data Structures_Ram_Disk Io - Fatal编程技术网

Python 存储/检索数据结构

Python 存储/检索数据结构,python,data-structures,ram,disk-io,Python,Data Structures,Ram,Disk Io,我在Python中实现了一个后缀树,用于进行全文搜索,它工作得非常好。但有一个问题:索引文本可能非常大,因此我们无法在RAM中拥有整个结构 图像:单词香蕉的后缀树(在我的场景中,想象一棵树大100000倍) 因此,我对它进行了一些研究,发现了pickle模块,这是一个很棒的Python模块,用于从文件中“加载”和“转储”对象,猜猜怎么着?它与我的数据结构配合得非常好 那么,让长话短说:在磁盘上存储和检索此结构的最佳策略是什么?我的意思是,一个解决方案可以是将每个节点存储在一个文件中,并在需要时

我在Python中实现了一个后缀树,用于进行全文搜索,它工作得非常好。但有一个问题:索引文本可能非常大,因此我们无法在RAM中拥有整个结构

图像:单词
香蕉的后缀树(在我的场景中,想象一棵树大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