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

时间:2013-05-07 18:54:02

标签: python c data-structures integer

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

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

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

那种糟糕的事情:

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

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

3 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:1)

为什么不直接存储一个包含自上次重写以来被删除的内容的表

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

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


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

保留单个表,很难知道何时可以删除项目,除非您知道它会影响多少个桶,而只需在删除表太大时重写所有存储桶。这可行,但它有点停止世界。

您还需要对流式传输的每对进行两次检查(例如,对于(3278, 15378),您需要检查327815378是否已被删除,而不仅仅是检查对(3278, 15378)是否已被删除。

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

答案 2 :(得分:-1)

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

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

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

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

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

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