适用于大量条目的最佳C语言键/值数据库

15

我正在尝试创建一个包含300,000,000个键值对,每个键和值都有8个字节的键值数据库。要求具有非常快的键值机制,每秒可以查询大约500,000个条目。

我尝试了BDB、Tokyo DB、Kyoto DB和LevelDB,但它们在处理如此大的数据库时性能都非常糟糕(它们的性能甚至远远达不到100万个条目的基准速度)。

由于硬件限制(32位软件),我不能将数据库存储在内存中,因此无法使用Memcached。

我也不能使用外部服务器软件(仅允许使用数据库模块),而且根本不需要多用户支持。当然,服务器软件也无法从单个端点处理每秒500,000次查询,所以Redis、Tokyo Tyrant等也无法使用。

7个回答

17

我是David Segleau,负责伯克利数据库的产品管理。

伯克利数据库性能最常见的问题是人们没有配置缓存大小,而是保留默认值,这个默认值相当小。其次,人们编写应用程序行为仿真器进行随机查找(尽管他们的应用程序实际上并非完全随机),这迫使他们从缓存读取数据。然后随机I/O会导致他们得出关于性能的结论,并不基于模拟应用程序而是实际应用程序的行为。

根据您的描述,我不确定您是否遇到了这些常见问题,或者可能遇到了完全不同的问题。在任何情况下,我们的经验是,伯克利数据库往往表现出色且可扩展性强。我们很乐意帮助您识别任何瓶颈,并提高您的BDB应用程序吞吐量。在这方面获得帮助的最佳途径是通过BDB论坛:http://forums.oracle.com/forums/forum.jspa?forumID=271。当您在论坛上发布时,最好展示应用程序代码中的关键查询段以及显示数据库环境性能的db_stat输出。

很可能您需要使用BDB HA/Replication来负载均衡多个服务器上的查询。每秒500K个查询可能需要一个更大的多核服务器或一系列更小的复制服务器。我们经常看到在普通硬件上运行的BDB应用程序具有100-200K个查询/秒,但是在32位应用程序中每秒处理300M条记录的500K个查询/秒很可能需要进行精细调整。我建议专注于优化在单个节点上运行的BDB应用程序的查询性能,然后使用HA将该负载分布到多个系统中以扩展您的查询/秒吞吐量。

希望这有所帮助。

祝您的应用顺利。

敬礼,

Dave


3
我找到了一个好的基准比较网页,基本上比较了5个著名的数据库:
  • LevelDB
  • Kyoto TreeDB
  • SQLite3
  • MDB
  • BerkeleyDB
在做出选择之前,你应该先查看一下它:http://symas.com/mdb/microbench/
附言:我知道你已经测试过它们,但你应该考虑到每个测试的配置都没有像基准测试所显示的那样进行优化。

1
你似乎忘记了使用BSD许可证的事务键/值存储UnQLite(http://unqlite.org),它是用ANSI C编写的。 - James
我知道还有更多,但是参考链接已经选择了上面的这些。 - Eran Betzalel
LevelDB、Kyoto TreeDB 和 SQLite3 被选中,因为它们是原始的 Google LevelDB 基准测试的一部分。http://leveldb.googlecode.com/svn/trunk/doc/benchmark.htmlLMDB 是目前最节省内存的数据库引擎,但正如另一个答案所指出的那样,在 32 位操作系统上使用 LMDB 时,如果没有进行自定义编译以将用户地址空间提高到 2GB 以上,则无法容纳此数据。在 64 位操作系统上,对于 LMDB 来说,这个工作量是微不足道的,而且没有其他任何东西能够接近其性能。http://symas.com/mdb/inmem/large.html - hyc

1

试试ZooLib

它提供了一个带有C++ API的数据库,最初是为教育机构的高性能多媒体数据库Knowledge Forum编写的。它可以处理3,000个同时运行的Mac和Windows客户端(也是用ZooLib编写的 - 它是一个跨平台应用程序框架),所有这些客户端都在流式传输音频、视频并使用由教师和学生创建的图形丰富的文档。

它有两个低级API,用于将字节实际写入磁盘。其中一个非常快,但不容错。另一个是容错的,但不如快速。

我是ZooLib的开发人员之一,但我对ZooLib的数据库组件没有太多经验。也没有文档 - 你必须阅读源代码才能弄清楚它的工作原理。这是我的错,因为十年前我接手编写ZooLib手册的工作,但几乎没有开始。

ZooLib的主要开发者Andy Green是个很棒的人,总是乐于回答问题。我建议你订阅ZooLib在SourceForge上的开发者列表,然后在列表上询问如何使用数据库。很可能Andy会亲自回答你,但也有可能是我们其他的开发者。
ZooLib是基于MIT许可证的开源软件,代码质量非常高,非常成熟。它从1990年左右开始持续开发,并于2000年放置在开源中。
不要担心我们自2003年以来没有发布tarball。我们可能应该这样做,因为这会让很多潜在用户认为它已经被放弃了,但它仍然被广泛使用和维护。只需从Subversion获取源代码即可。
Andy是一名自雇顾问。如果你没有时间但有预算,他会非常出色地编写定制、可维护的高质量C++代码以满足你的需求。
如果除了数据库之外的任何ZooLib部分,我都可以做到,因为我对数据库不熟悉。我已经用ZooLib的UI框架做了很多自己的咨询工作。

1

300 M * 8 字节 = 2.4GB。如果操作系统没有将地址空间限制在31位,则可能适合内存。 由于您还需要处理溢出(通过重新散列方案或链接),因此内存变得更加紧张,对于线性探测,您可能需要> 400M个插槽,链接将使项的大小增加到12字节(位操作可能会为您节省一些位)。这将将总占用空间增加到约3.6 GB。

无论如何,您都需要一个特别设计的内核,将其自己的“保留”地址空间限制在几百MB。这并非不可能,但是是一项重大操作。在所有情况下,转移到基于磁盘的东西将太慢了。(PAE可以为您节省,但它很棘手)

我认为您最好的选择是迁移到64位平台。


1

每秒处理500,000个条目而不将工作集保留在内存中?哇。

一般情况下,使用硬盘驱动器甚至困难的固态硬盘也无法实现这一点。

您是否有任何本地化属性可以帮助简化任务?您有什么样的查询需求?


0

我们使用Redis。它用C语言编写,设计上只比memcached略微复杂一些。我们从未尝试使用过太多行,但对于我们来说延迟非常重要,它可以很好地处理这些延迟并让我们将数据存储在磁盘中。

这里有一篇基准测试博客文章,比较了redis和memcached。


0

Berkely DB可以为您完成这项工作。 我在8年前实现了每秒50000个插入操作,并获得了最终的700亿条记录的数据库。


你还记得这个的吞吐量是多少吗?另外,插入的值是否以相当快的速度进行且数量很大?(抱歉提及旧帖子中的内容,但我真的很好奇...) - AO_

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接