【问题标题】:BerkeleyDB write performance problemsBerkeleyDB 写入性能问题
【发布时间】:2011-07-22 08:30:57
【问题描述】:

我需要一个基于磁盘的键值对存储,它可以为大型数据集维持高写入和读取性能。我知道,要求很高。

我正在尝试来自 java 的 C BerkeleyDB (5.1.25) 库,但遇到了严重的性能问题。

我在短时间内获得了稳定的 14K 文档/秒,但是一旦我达到几十万个文档,性能就会像石头一样下降,然后恢复一段时间,然后再次下降,等等。这种情况越来越多,而且更频繁地,在大多数情况下,在 1000 万个文档之后,我无法获得超过 60 个文档/秒的几个孤立峰值 12K 文档/秒。我选择的数据库类型是 HASH,但我也尝试过 BTREE,它是一样的。

我尝试使用 10 个 db 的池并在其中散列文档以消除性能下降;这将写入吞吐量提高到 50K docs/s,但对性能下降没有帮助:所有 10 db 同时减速到爬行。

我认为文件正在被重组,我试图找到一个影响重组发生时间的配置参数,因此每个池化数据库都会在不同的时间重组,但我找不到任何有用的东西.我尝试了不同的缓存大小,使用 setHashNumElements 配置选项保留空间,这样它就不会花时间增长文件,但每次调整都让它变得更糟。

我即将放弃 berkeleydb 并尝试更复杂的解决方案,例如 cassandra,但我想确保在 berkeleydb 注销之前我没有做错什么。

这里有人有使用 berkeleydb 实现持续写入性能的经验吗?

编辑 1

我已经尝试了几件事:

  1. 将写入速度降低到 500/s(低于我在 15 小时内写入 3000 万个文档后得到的平均值,这表明硬件能够写入 550 个文档/秒)。不起作用:一旦编写了一定数量的文档,性能就会下降。
  2. 将传入项目写入队列。这有两个问题:A)它破坏了释放内存的目的。 B) 队列最终会阻塞,因为 BerkeleyDB 冻结的时间越来越长且越来越频繁。

换句话说,即使我限制传入数据以保持低于硬件能力并使用 ram 来保存项目,而 BerkeleyDB 需要一些时间来适应增长,随着时间越来越长,性能接近 0。

这让我感到惊讶,因为我已经看到声称它可以处理 TB 的数据,但我的测试表明并非如此。我仍然希望我做错了什么......

编辑 2

经过深思熟虑并根据 Peter 的意见,我现在了解到,随着文件变大,一批写入将分散得更远,并且它们落入同一个磁盘柱面的可能性会下降,直到最终达到磁盘的搜索次数/秒限制。

但是,BerkeleyDB 的定期文件重组比这更早地扼杀了性能,而且以更糟糕的方式:它只是停止响应的时间越来越长,同时它随机播放数据。使用更快的磁盘或将数据库文件分布在不同的磁盘之间并没有帮助。我需要找到解决这些吞吐量漏洞的方法。

【问题讨论】:

    标签: java performance berkeley-db key-value


    【解决方案1】:

    我所看到的磁盘写入率高的情况是,系统缓存会被填满(在此之前提供轻量级的性能),但一旦填满应用程序,甚至整个系统都会显着减慢,甚至停止。

    您的底层物理磁盘应支持每秒至少 100 次写入。除此之外,更清晰的缓存支持的错觉。 ;) 但是,当缓存系统耗尽时,您会看到非常糟糕的行为。

    我建议您考虑使用磁盘控制器缓存。它的电池备份内存需要与您的数据大小差不多。

    如果更新是突发性的,另一种选择是使用 SSD 驱动器(它们每秒可以进行 10K+ 写入,因为它们没有移动部件)和缓存,这应该会给您提供比您需要的更多的东西,但 SSD 的写入次数有限.

    【讨论】:

    • 我看到在每秒 70 次搜索的磁盘上平均每秒写入 500 次(这要归功于控制器缓存,对吗?)。如果我能获得恒定的 500 次写入/秒,我会很满意,但我得到了一个我想避免的巨大可变性。我尝试将写入速度降低到 500/s,但是一旦写入了一定数量的文档,性能无论如何都会下降。 SSD 不是一个选项。
    • @user305175:要查看磁盘是否有问题,您可以尝试两件事:在 Windows 上使用 PerfMon 或在 Linux 上使用 vmstat 监控磁盘 IO 性能。或者,如果您有足够的 RAM,请尝试在 RAM-only 模式下使用 BerkeleyDB。
    • @Zan:使用 BerkeleyDB 的全部意义在于从内存中卸载东西。问题是 BerkeleyDB 似乎无法提供稳定的写入性能。
    • @Alex:我说的是调试。如果调试发现磁盘 IO 问题,那么您购买 SSD 或其他任何东西。
    • 我的意思是你的硬件很可能是性能不稳定的根本原因。操作系统/软件只能做很多事情来解决您的硬件限制。我猜你看到的 CPU 时间很少,主要是在等待磁盘。不要只是从我这里拿走它。 7200 RPM 磁盘的典型访问时间为 8 毫秒,这意味着您可以持续每秒执行 125 次写入。 (1000/8)tomshardware.com/reviews/notebook-hdd-750gb,2832-7.htm
    【解决方案2】:

    BerkeleyDB 不执行文件重组,除非您手动调用压缩实用程序。减速有几个原因:

    1. 以随机访问方式写入密钥,这会导致更高的磁盘 I/O 负载。
    2. 默认情况下写入是持久的,这会强制进行大量额外的磁盘刷新。
    3. 正在使用事务环境,在这种情况下,检查点会在将更改刷新到磁盘时导致速度变慢。

    当您说“文档”时,您的意思是说您正在使用 BDB 来存储大于几 KB 的记录吗? BDB 溢出页面的开销更大,因此您应该考虑使用更大的页面大小。

    【讨论】:

      【解决方案3】:

      我们在工作中使用过 BerkeleyDB (BDB),并且性能趋势似乎相似。 BerkeleyDB 使用 Btree 来存储其键/值对。当条目数不断增加时,树的深度会增加。 BerkeleyDB 缓存用于将树加载到 RAM 中,因此树遍历不会产生文件 IO(从磁盘读取)。

      【讨论】:

      • 您尝试过 BDB 分区吗?我自己没有尝试过,因此无法用事实支持我的建议。
      • Berkeley DB 使用 B+树,而不是 B-树(尽管 BDB 叫它们)。见aosabook.org/en/bdb.html
      【解决方案4】:

      这是一个老问题,问题可能已经消失了,但是我最近遇到了类似的问题(插入速度在几十万条记录后急剧下降)并且通过向数据库提供更多缓存来解决它们(DB->set_cachesize )。使用 2GB 的缓存,插入速度非常好,并且或多或少保持不变,最多可达 1000 万条记录(我没有进一步测试)。

      【讨论】:

      • 这个答案对我帮助很大!将缓存增加到 8GB 使我能够顺利导入近 1 亿条记录。如果有人对如何使用 Python3 绑定设置缓存大小感兴趣,请参阅my commit here。也不要同时导入两个数据库!
      【解决方案5】:

      我需要一个基于磁盘的键值对存储,能够为大型数据集维持高读写性能。

      Chronicle Map 是此任务的现代解决方案。它在读取和写入方面都比 BerkeleyDB much faster,并且在来自多个线程/进程的并发访问方面更具可扩展性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-30
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-23
        相关资源
        最近更新 更多