繁体   English   中英

用于在磁盘上有效存储整数对集的数据结构选项?

[英]Data structure options for efficiently storing sets of integer pairs on disk?

我有一堆处理文档聚类的代码。 一步涉及计算每个文档与给定语料库中的每个其他文档的相似性(对于“类似”的一些不重要的定义),并存储相似性以供以后使用。 相似之处是不同的,我不关心具体的相似性是什么,我的分析的目的,只是它在什么桶。例如,如果文件15378和3278是52%相似,有序对(3278,15378)得到存储在[0.5,0.6]桶中。 在初始分析之后,文档有时会从语料库中添加或删除,因此根据需要将相应的对添加到桶中或从桶中删除。

我正在研究存储这些ID对列表的策略。 我们发现一个SQL数据库(这个项目的大多数其他数据都存在)对于我们的目的来说太慢而且磁盘空间太大,所以目前我们将每个存储桶存储为磁盘上的整数压缩列表(最初zlib压缩,但现在使用lz4代替速度)。 我喜欢这件事:

  • 阅读和写作都非常快
  • 语料库的事后添加是相当简单的添加(对于lz4比对zlib少一点,因为lz4没有内置的框架机制,但可行)
  • 在写入和读取时,数据都可以流式传输,因此不需要一次性保存在内存中,考虑到我们的语料库大小,这将是令人望而却步的

有点糟糕的事情:

  • 删除是一个巨大的痛苦,基本上涉及流式传输所有桶并写出新的,省略任何包含已被删除的文档的ID的对
  • 我怀疑通过更专用的数据结构和/或压缩策略,我在速度和紧凑性方面仍然可以做得更好

那么:我应该关注哪种数据结构? 我怀疑正确的答案是某种奇特的简洁数据结构,但这不是我所熟知的空间。 此外,如果重要:所有文档ID都是无符号的32位整数,处理这些数据的当前代码是用C语言编写的,作为Python扩展,所以这可能是我们将坚持的通用技术系列。

如何在每个桶中使用一个哈希表或B树?

磁盘哈希表是标准的。 也许BerkeleyDB库(可用于库存python)将为您服务; 但要注意他们,因为他们来自交易,他们可能会很慢,可能需要一些调整。 有很多选择:gdbm,tdb,你们都应该尝试一下。 只需确保检查API并使用适当的大小初始化它们。 有些不会自动调整大小,如果你给它们提供太多数据,它们的性能就会下降很多。

无论如何,如果你有很多变化,你可能想要使用更低级别的东西而不进行交易。

一对int是一个很长的 - 大多数数据库应该接受一个长的密钥; 事实上,许多人会接受任意字节序列作为键。

为什么不只存储一个包含自上次重写后删除的内容的表?

此表可以与您的主存储桶具有相同的结构,也可以使用Bloom过滤器进行快速成员资格检查。

您可以在没有删除项目的情况下重新编写主存储桶数据,或者当您要重新编写它以进行其他修改时,或者删除项目的比率:存储桶大小超过某个阈值时。


此方案可以通过将每个已删除的对存储在每个存储桶旁边,也可以通过为所有已删除的文档存储单个表来实现:我不确定哪个更适合您的要求。

保留一个表,很难知道什么时候可以删除项目,除非你知道它影响了多少桶,而不是只要删除表太大就重写所有桶。 这可能有用,但它有点停止世界。

您还必须对流入的每对进行两次检查(即,对于(3278, 15378) ,您要检查是否已删除327815378 ,而不是仅检查是否已删除对(3278, 15378)

相反,每个已删除对的每个桶表需要更长时间才能构建,但检查时要快一些,并且在重写桶时更容易崩溃。

您正在尝试重新发明新时代NoSQL数据存储中已存在的内容。 有2个非常好的候选人符合您的要求。

  1. Redis的。
  2. MongoDB的

两者都支持数据结构,如字典,列表,队列。 像追加,修改或删除这样的操作也可用,并且非常快。

它们的性能是由可以驻留在RAM中的数据量驱动的。 由于您的大多数数据都是基于整数的,因此不应该成为问题。

我个人的建议是使用Redis,具有良好的持久性配置(即数据应定期从RAM保存到磁盘)。

以下是redis数据结构的简介: http ://redis.io/topics/data-types-intro

redis数据库是一个轻量级安装,客户端在Python中可用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM