MongoDB与CouchDB(速度优化)

我做了一些速度testing来比较MongoDB和CouchDB。 只有插入是在testing。 我得到的MongoDB比CouchDB快15倍。 我知道这是因为socketsVS http。 但是,这对我来说非常有趣,我如何优化CouchDB中的插入?

testing平台:Windows XP SP3 32位。 我使用了最新版本的MongoDB,MongoDB C#Driver和CouchDB for Windows 安装包的最新版本。

谢谢!

Solutions Collecting From Web of "MongoDB与CouchDB(速度优化)"

为了将大量数据以批量方式插入到数据库中,CouchDB支持在HTTP批量文档API下的wiki中描述的批量插入

此外,请查看delayed_commits配置选项,以及上述链接中描述的batch=ok选项。 这些选项启用类似的内存缓存行为,并对磁盘进行定期同步。

只是迭代在与HTTP和fsync与内存中的会话的套接字。

默认情况下,MongoDB不会在写入调用中返回响应。 您只需将数据写入套接字,并假设它在数据库中并可用。 在并发负载情况下,这可能会得到备份,并且没有一个好的方法来知道Mongo的真正速度,除非您使用一个可选的调用,一旦数据可用,就会返回写入响应。

我并不是说Mongo插入性能不如Couch快,插入内存比fsyncing to disc要快很多,这里的区别在于MongoDB和CouchDB在一致性和持久性方面的差异。 但是我所见过的用于测试Mongo的所有“性能”工具都使用默认的写入API,因此您并不真正在测试插入性能,而是测试可以刷新到套接字的速度。

我看到很多基准测试显示Mongo比Redis和memcached更快,因为他们没有意识到Redis和Memcached在内存中返回响应,而Mongo没有响应。 Mongo肯定不会比Redis快

我不认为套接字和http之间的区别是唯一的区别。 差异也与磁盘同步(fsync)有关。 这影响耐久性。 MongoDB首先将所有内容存储在RAM中,并且它只能以特定的时间间隔同步到磁盘,除非您明确告诉MongoDB执行fsync。

阅读耐久性和MongoDB: http : //blog.mongodb.org/post/381927266/what-about-durability和fsync: http : //www.mongodb.org/display/DOCS/fsync+Command

这是我一直在想的一个想法,但没有进行基准测试。 我希望在某些情况下它会很棒:

  • 插入吞吐量必须很高
  • 通过密钥获取单个文档不是必需的
  • 所有数据都是通过视图获取的(可能是与接收插入的机器不同的机器)

计划

插入批处理批处理文档,并使用视图序列化它们很好地返回。

考虑一个简单的时间戳和消息字符串的日志文件。

 0.001 Start 0.123 This could be any message 0.500 Half a second later! 1.000 One second has gone by 2.000 Two seconds has gone by [...] 1000.000 One thousand seconds has gone by 

您可能会在每个文档中插入一条日志,例如:

 { "_id": "f30d09ef6a9e405994f13a38a44ee4a1", "_rev": "1-764efa883dda1e11db47671c4a3bbd9e", "timestamp": 0.123, "message": "This could be any message" } 

标准批量文档优化

第一个优化是使用_bulk_docs插入,如在CouchDB批量文档文档中一样 。

二次批量插入优化

但是, 第二个优化是将日志预批量处理成一个更大的Couch文档 。 例如,分4个批次(在现实世界中这将会高得多):

 { "_id": "f30d09ef6a9e405994f13a38a44ee4a1", "_rev": "1-764efa883dda1e11db47671c4a3bbd9e", "logs": [ {"timestamp": 0.001, "message": "Start"}, {"timestamp": 0.123, "message": "This could be any message"}, {"timestamp": 0.500, "message": "Half a second later!"}, {"timestamp": 1.000, "message": "One second has gone by"} ] } { "_id": "74f615379d98d3c3d4b3f3d4ddce82f8", "_rev": "1-ea4f43014d555add711ea006efe782da", "logs": [ {"timestamp": 2.000, "message": "Two seconds has gone by"}, {"timestamp": 3.000, "message": "Three seconds has gone by"}, {"timestamp": 4.000, "message": "Four seconds has gone by"}, {"timestamp": 5.000, "message": "Five seconds has gone by"}, ] } 

当然,你也可以通过_bulk_docs来插入这些数据 ,从而有效地插入批量的批量数据

意见还是很容易的

将日志序列化回视图仍然非常容易:

 // map function(doc) { if(doc.logs) { // Just unroll the log batches! for (var i in doc.logs) { var log = doc.logs[i]; emit(log.timestamp, log.message); } } } 

那么在startkeyendkey或其他你需要的东西之间取时间记录是很容易的。

结论

这仍然没有基准,但我的希望是,对于某些类型的数据,批量化会减少内部B树写入。 结合_bulk_docs ,我希望看到插入吞吐量达到硬盘的硬件速度。