7

我很难在我的 SSD 上使用哈希数组存储数亿个 16/32 字节的键/值对。

使用京都内阁:当它工作正常时,它以 70000 条记录/秒的速度插入。一旦下降,它就会下降到 10-500 条记录/秒。在默认设置下,下降发生在大约一百万条记录之后。查看文档,这是数组中存储桶的默认数量,所以这是有道理的。我将这个数字增加到 2500 万,实际上,它可以正常工作,直到大约 2500 万条记录。问题是,一旦我将存储桶的数量推到 3000 万或更多,插入速率从一开始就下降到 10-500 条记录/秒。京都内阁不是为了在创建数据库后增加桶的数量而设计的,所以我不能插入超过 2500 万条记录。

1/为什么一旦桶数超过25M,KC的插入率会变得非常低?

使用 Berkeley DB:我得到的最佳速度略低于 KC,接近 50000 条记录/秒,但还可以。使用默认设置,就像 KC 一样,在大约一百万条记录后速度会突然下降。我知道 BDB 旨在逐渐扩展其存储桶的数量。尽管如此,它尝试增加初始数量,使用 HashNumElements 和 FillFactor,但任何这些尝试都使情况变得最糟糕。所以我仍然无法使用 DBD 插入超过 1-2 百万条记录。我尝试激活非同步事务,尝试不同的检查点速率,增加缓存。没有什么能改善下拉菜单。

2/什么会导致 BDB 的插入率在 1-2 百万次插入后下降?

注意:我正在使用 java,当速度下降时,CPU 使用率会降低到 0-30%,而以正确的速度工作时会达到 100%。
注意:停止该过程并恢复插入不会改变任何内容。所以我认为这与内存限制或垃圾收集无关。

谢谢。

4

1 回答 1

3

以下是我如何在 KC 遇到写入限制的情况下设法存储数十亿条记录。

经过一番努力,我仍然没有解决京都内阁和伯克利数据库的问题。然而,我想出了一个有趣的解决方法,使用京都内阁。

我注意到我不能在一个 KC 文件上写入超过 25M 的记录,但读取没有这样的限制——它总是很快,不管数据库的大小。我找到的解决方案是为每 25M 新记录创建一个新的 KC 文件(一个新数据库)。这样,读取发生在许多 KC 文件上并且仍然很快,而写入仅发生在最后创建的文件上并且也很快。唯一剩下的问题是允许更新/删除以前文件上的记录。为此,我复制了 SSTables 方法,即:

  • 所有0到N-1个文件都是只读的,文件N是读+写的。
  • 任何插入/更新/删除都写入文件 N。
  • 读取查找文件 N 到 0,并返回第一次看到/最后写入的插入/更新/删除。
  • 每个文件都附加了一个布隆过滤器,以避免访问没有所需记录的文件。
  • 一旦文件 N 达到 25M 记录,它就变为只读并创建文件 N+1。

备注:

  • 就像 SSTables 一样,如果执行了很多更新/删除,我们可能想要执行压缩。然而,与 SSTables 不同的是,这里的压缩不需要重写文件。过时的记录简单地从 KC 文件中删除,如果 KC 文件变得非常小,则可以将其删除 - 重新插入文件 N 中的记录 - 或重新打开以进行新插入 - 前提是下一个文件是紧凑的。
  • 删除不会删除记录,但会写入一个特殊值,将记录标识为已删除。在压缩期间,删除的记录会被真正删除。
  • 检查记录是否存在通常需要查看数据库。多亏了布隆过滤器,大多数否定答案都可以在没有任何磁盘访问的情况下给出。
于 2012-10-25T22:48:35.580 回答