这是否会导致MongoDB性能问题(通过'破坏'游标'在客户端执行`limit`)?

时间:2011-05-09 18:02:58

标签: performance mongodb

虽然这与PHP没有任何关系,但我在以下示例中使用了PHP。

让我们说这是限制结果的“正常”方式。

$db->users->find()->limit(10);

这可能是最快的方法,但这里有一些限制......在下面的例子中,我将过滤掉所有具有某一列保存值的行作为前一行:

$cursor = $db->users->find();
$prev = null;
$results = array();
foreach ($cursor as $row) {
    if ($row['coll'] != $prev['coll']) {
        $results[] = $row;
        $prev = $row;
    }
}

但是你仍然希望将结果限制为10,当然。所以你可以使用以下内容:

$cursor = $db->users->find();
$prev = null;
$results = array();
foreach ($cursor as $row) {
    if ($row['coll'] != $prev['coll']) {
        $results[] = $row;
        if (count($results) == 10) break;
        $prev = $row;
    }
}

说明:由于$cursor实际上并未加载数据库中的结果,因此break - foreach limit循环limit(...)就像{{1}}一样} -function确实。

可以肯定的是,这是否真的像我说的那样有效,还是有任何我不知道的性能问题?

非常感谢, 添

1 个答案:

答案 0 :(得分:1)

  

说明:由于$ cursor实际上并没有从数据库中加载结果,因此打破foreach循环将限制它,就像限制(...) - 函数一样。

这不是100%正确。

当您执行foreach时,您基本上会发布一系列循环访问数据的hasNext / getNext

但是,在此图层下方,驱动程序实际上是在请求和接收批量结果。当您执行getNext时,驱动程序将为您无缝地获取下一批。

您可以控制批量大小。文档中的详细信息应该有助于clarify what's happening

在你的第二个例子中,如果你到10,然后break,有两个副作用:

  1. 光标在服务器上保持打开状态(10分钟内超时,通常影响不大)。
  2. 您可能会在$cursor中缓存更多数据。 $cursor超出范围时,此缓存将消失。
  3. 在大多数情况下,这些副作用“并不是什么大问题”。但是如果你在一个过程中进行大量的处理,你就会想要“清理”以避免游标停留。