【问题标题】:What is the fastest way to store huge amount of unique strings?存储大量唯一字符串的最快方法是什么?
【发布时间】:2012-04-25 16:31:12
【问题描述】:

我想知道存储大量字符串和检查重复的最佳方法是什么。

我们必须考虑我们的优先事项:

  • 重复检查速度
  • 插入新的字符串时间
  • 硬盘上的存储空间
  • 随机访问时间

当我们的目标是快速重复检查和插入新字符串时(没有随机访问或存储空间问题),最好的解决方案是什么? 我想到了 SQL 数据库,但哪个 DB 最适合这个解决方案? 如果我们使用 SQL DB,比如 MySQL,哪个存储引擎是最好的? (当然,由于数据量,我们必须排除内存)

【问题讨论】:

  • 您能否详细说明“随机访问时间”的含义?如果您的数据是一组字符串,您将拥有的唯一操作是“添加”、“包含”和“删除”。
  • 如果您告诉我们更多关于您的问题的信息,我们可以为您提供更好的帮助,例如,如果您在运行时处理字符串,但内存足够大,最好的方法是将它们存储在一个列表/哈希/数组,并且仅在它们不存在时才添加项目,然后在最后写出数组(如果您在运行后需要它,请再次详细说明)。
  • 您是在尝试组合不同字符串的集合、过滤重复项还是什么?目的是什么?特别是:重复的预期分数是多少?您是否希望几乎所有内容都是重复的,或者这是一个罕见的事件?是否要将所有新值添加到数据库中?
  • 主要目标是检查给定的字符串(哈希)是否已经被检查=搜索重复。每 10 次检查重复计数约 1-3 次。所有新值都应添加到数据库中(可以作为哈希)。

标签: algorithm storage


【解决方案1】:

对输入字符串使用哈希函数。输出哈希将是记录的主键/ID。

然后你可以检查数据库是否有这个hash/id/primary key:

  • 如果没有:这是一个新字符串;您添加一条新记录,包括字符串和哈希作为 id。
  • 如果是:检查加载记录中的字符串是否与输入字符串相同。
    • 如果字符串相同:重复
    • 如果字符串不同:这是一个冲突。使用collision resolution 方案来解决。 (下面有几个例子)

您必须根据速度和预期的字符串数量以及哈希冲突要求/保证来考虑使用哪种哈希函数/方案/强度。

解决冲突的几种方法:

  • 使用第二个散列函数在同一个表中产生一个新的散列。
  • 标记记录(例如,使用 NULL)并在辅助“冲突”表上使用更强的第二个散列函数(具有更广泛的域)重复。在查询时,如果字符串被标记为冲突(例如 NULL),则在冲突表中再次进行查找。您可能还想使用dynamic perfect hashing 来确保第二个表没有进一步的冲突。

当然,根据需要的持久性以及您期望占用多少内存/字符串数量,您实际上可以在没有数据库的情况下直接在内存中执行此操作,这样会快得多。

【讨论】:

  • 哈希作为主键?你如何处理碰撞?
  • 为什么要使用主键?一个带有“hash”列(非唯一)和一个“value”列(包含字符串)以及“hash”列上的聚集索引的简单表将使“select 1 from string where hash = 'hash' and value = '...'" 非常快速且非常简单,但插入速度有点慢。
  • @NicolasRepiquet 主键的主要动机是数据库强制执行冲突的概念。没有它,您可以插入具有相同哈希和不同字符串的多条记录,并且数据库将允许它。如果您使用seperate chaining,这可能是可取的,否则可能不是。如果我错了,请纠正我
  • "没有它,您可以插入多个具有相同哈希值和不同字符串的记录,并且数据库会允许这样做。"这不正是我们想要的吗?哈希在这里是为了缩小我们必须比较的字符串集,而不是作为唯一标识符。这当然是我的观点:)
  • @NicolasRepiquet 您所考虑的模型基本上是 DB-equivalent 的 seperate chaining 哈希冲突解决策略。在病态/最坏的情况下,想象所有字符串都映射到同一个哈希(通过一些纯粹的巧合/废话哈希函数)。在最坏的情况下,散列没有任何好处。
【解决方案2】:

您可能需要考虑 NoSQL 解决方案:

Redis。使用 Redis 解决的一些用例:

memcached。 memcached和Redis的一些比较:

Membase/Couchbase 将 OMGPOP 的 Draw Something 视为 one of their success stories。 Redis 和 Membase 的比较:

一些问题:

  • 字符串集有多大?
  • 应用程序是读取繁重还是写入繁重?还是两者兼有?
  • 您希望多久将数据持久化到磁盘?
  • 是否有 N 个最近的字符串要求?

希望这会有所帮助。

【讨论】:

  • 谢谢,不知道 Redis。不敢相信我以前没有听说过。 +1
【解决方案3】:

生成后缀树来存储字符串。 http://www.daimi.au.dk/~mailund/slides/Ukkonen-2005.pdf 中的 Ukkonen 算法将提供一些关于如何创建后缀树的见解。存储此后缀树的方法有多种。但是一旦生成,查找时间非常短。

【讨论】:

    猜你喜欢
    • 2016-01-03
    • 1970-01-01
    • 2017-05-29
    • 2019-12-25
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2014-09-03
    相关资源
    最近更新 更多