2

在将 mongo 作为数据库的设置上进行负载测试时,我注意到 mongo 经常记录属于同一操作的这种类型的消息:

Thu May 16 20:44:20.101 [conn3] command voterdb.$cmd command: { group: { ns: "vote",
$reduce: function ( curr, result ) { result.count++; }, cond: { p: "59a0f4cd-8c0c-49c4-
8a11-0e1ac6d89c4a" }, initial: { count: 0 }, out: "inline", key: { p: 1, q: 1, a: 1 } }  
} ntoreturn:1 keyUpdates:0 numYields: 2 locks(micros) r:228316 reslen:876 136ms

该应用程序很简单,我将文档添加到集合中,并且添加的每个文档都需要更新属于每种类型的文档数量。因此在此集合中的文档按类型分组的情况下执行分组操作。

我注意到的是,当测试完成时,mongo 继续显示这些消息,并在测试结束几分钟后处理这些分组查询(这意味着查询被延迟处理)。

我读到 mongo 是贪婪的作家,我还读到了关于 yield 操作的文章。我是否正确假设插入优先于分组并且正在产生分组操作导致测试后处理?

4

1 回答 1

3

MongoDB 在数据库上使用读取器和写入器锁,这意味着写入器在数据库上持有排他锁,而多个读取器可以共享锁。为了防止长时间运行的操作阻塞写入器和读取器队列,MongoDB 支持屈服。主要方法是围绕这样的想法,即应该首先快速提供内存中的操作,而不必等待进入磁盘的操作。下面的链接提供了有关收益和分析统计的更多细节。

http://docs.mongodb.org/manual/faq/concurrency/#faq-concurrency-yielding http://docs.mongodb.org/manual/reference/database-profiler/

还有一些关于您的应用程序描述的想法。我将不得不详细介绍具体推荐最佳方法,但我觉得你正在做的事情有一个更有效的设计。

  1. 使用 Aggregation Framework 与 Map Reduce:看起来您可能正在使用 MR 流程来执行您的计数。聚合框架的开销显着减少,并且几乎总是更快。

  2. 如果事实证明你只是在做一个计数,看看你是否可以简单地做一个 db.collection.find({..}).count() 因为这将非常快。计数缓存在索引中。

  3. 最后,您是否需要对插入的每个文档执行聚合?有多种选择。例如,您只想增加($inc)某个计数器,或者在后台定期执行聚合。完美的场景是以类型的粒度存储文档是可行的,这将允许您在一个操作中进行计数和插入。

于 2013-08-16T07:29:43.933 回答