我需要一个基于磁盘的键值存储,它可以维持大数据集的高写入和读取性能。很高,我知道。
我正在尝试使用Java的C BerkeleyDB(5.1.25)库,我看到了严重的性能问题。
我在短时间内获得了稳定的14K docs / s,但是当我达到几十万个文档时,性能会像摇滚一样下降,然后它会恢复一段时间,然后再次下降,等等。更常见的是,在大多数情况下,我无法获得超过60个docs / s,并且在1000万个docs之后有一些12K docs / s的孤立峰值。我的db类型选择是HASH,但我也试过BTREE,它是一样的。
我尝试使用10 db的池并在其中散列文档以消除性能下降;这使写入吞吐量增加到50K docs / s,但对性能下降没有帮助:所有10 db都同时减慢了爬行速度。
我假设文件正在重组,我试图找到一个影响何时进行重组的配置参数,因此每个池化的db会在不同的时间重新组织,但我找不到任何有效的东西。我尝试了不同的缓存大小,使用setHashNumElements配置选项保留空间,这样就不会花时间增长文件,但每次调整都会让它变得更糟。
我准备给berkeleydb并尝试更复杂的解决方案,比如cassandra,但我想确保在写下来之前我没有在berkeleydb做错事。
此处有人在berkeleydb获得持续写作表现的经验吗?
修改1 :
我已经尝试了几件事:
换句话说,即使我限制传入数据保持低于硬件功能并使用ram来保存项目,而BerkeleyDB需要一些时间来适应增长,因为这个时间越来越长,性能接近0。
这令我感到惊讶,因为我已经看到声称它可以处理数TB的数据,但我的测试显示不然。我仍然希望我做错了...
编辑2 :
在给予它更多的思考和Peter的输入之后,我现在明白随着文件变大,一批写入将会分散得更远,并且它们落入相同磁盘柱的可能性会下降,直到最终达到磁盘的搜索/第二限制。
但是BerkeleyDB的定期文件重组比这更早地杀死了性能,并且以更糟糕的方式:它只是停止响应更长和更长的时间,同时它会改变周围的东西。使用速度更快的磁盘或在不同磁盘之间传播数据库文件无济于事。我需要找到解决这些吞吐量漏洞的方法。
答案 0 :(得分:2)
我所看到的高磁盘写入速率是系统缓存将填满(在此点之前提供闪电性能)但是一旦它填满应用程序,即使整个系统也会大幅减速,甚至停止。
您的底层物理磁盘应至少每秒支持100次写入。除此之外,更清晰的缓存支持幻觉。 ;)但是,当缓存系统耗尽时,您会看到非常糟糕的行为。
我建议您考虑使用磁盘控制器缓存。其电池备份内存需要与您的数据大小相当。
另一种选择是使用SSD驱动器,如果更新是突发性的(它们可以每秒10K +写入,因为它们没有移动部件)和缓存,这应该比你需要的多,但是SSD的写入次数有限
答案 1 :(得分:1)
除非您手动调用压缩实用程序,否则BerkeleyDB不会执行文件重组。导致经济放缓的原因有几个:
当你说“文档”时,你的意思是说你使用BDB来存储大于几千字节的记录吗? BDB溢出页面有更多开销,因此您应该考虑使用更大的页面大小。
答案 2 :(得分:1)
我们在工作中使用了BerkeleyDB(BDB)并且看起来有类似的性能趋势。 BerkeleyDB使用Btree来存储其键/值对。当条目数量不断增加时,树的深度会增加。 BerkeleyDB缓存可以将树加载到RAM中,因此树遍历不会导致文件IO(从磁盘读取)。
答案 3 :(得分:1)
这是一个老问题,问题可能已经消失,但我最近遇到了类似的问题(插入速度在数十万条记录之后急剧下降)并且它们通过向数据库提供更多缓存来解决(DB-> set_cachesize)。使用2GB的缓存,插入速度非常好,并且或多或少地保持高达1000万条记录(我没有进一步测试)。
答案 4 :(得分:0)
我需要一个基于磁盘的键值存储,可以维持大数据集的高写入和读取性能。
Chronicle Map是此任务的现代解决方案。它在读取和写入方面比BerkeleyDB much faster,并且在来自多个线程/进程的并发访问方面更具可伸缩性。