这是否会导致 MongoDB 性能问题(通过“破坏”“光标”在客户端执行“限制”时)?

发布于 2024-11-06 00:40:29 字数 919 浏览 0 评论 0原文

虽然这与 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 实际上并未从数据库加载结果,因此 breaking foreach 循环将像 limit(...) 函数一样限制它。

可以肯定的是,这真的像我所说的那样有效吗?或者是否存在我不知道的性能问题?

非常感谢, 蒂姆

Though this has nothing to do with PHP specifically, I use PHP in the following examples.

Let's say this is the 'normal' way of limiting results.

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

This is probably the fastest way, but there are some restrictions here... In the following example, I'll filter out all rows that have the save value for a certain column as the previous row:

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

But you still want to limit the results to 10, of course. So you could use the following:

$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;
    }
}

Explanation: since the $cursor does not actually load the results from the database, breaking the foreach-loop will limit it just as the limit(...)-function does.

Just for sure, is this really working as I'm saying, or are there any performance issues I'm not aware of?

Thank you very much,
Tim

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

失眠症患者 2024-11-13 00:40:29

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

这并非100%正确。

当您执行 foreach 时,您基本上会发出一系列 hasNext / getNext 正在循环数据。

然而,在这一层之下,驱动程序实际上正在请求和接收批量结果。当您执行getNext时,驱动程序将无缝地为您获取下一批。

您可以控制批量大小。文档中的详细信息应该有助于澄清发生了什么

在第二个示例中,如果达到 10,然后 break,则会产生两个副作用:

  1. 游标在服务器上保持打开状态(10 分钟后超时,通常影响不大)。
  2. 您可能在 $cursor 中缓存了更多数据。当 $cursor 超出范围时,此缓存将消失。

在大多数情况下,这些副作用“没什么大不了的”。但是,如果您在单个进程中执行大量此类处理,您将需要“清理”以避免光标徘徊。

Explanation: since the $cursor does not actually load the results from the database, breaking the foreach-loop will limit it just as the limit(...)-function does.

This is not 100% true.

When you do the foreach, you're basically issuing a series of hasNext / getNext that is looping through the data.

However, underneath this layer, the driver is actually requesting and receiving batches of results. When you do a getNext the driver will seamlessly fetch the next batch for you.

You can control the batch size. The details in the documentation should help clarify what's happening.

In your second example, if you get to 10 and then break there are two side effects:

  1. The cursor remains open on the server (times out in 10 minutes, generally not a big impact).
  2. You may have more data cached in $cursor. This cache will go away when $cursor goes out of scope.

In most cases, these side effects are "not a big deal". But if you're doing lots of this processing in a single process, you'll want to "clean up" to avoid having cursors hanging around.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文