这是否会导致 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
ing 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, break
ing 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这并非100%正确。
当您执行
foreach
时,您基本上会发出一系列hasNext
/getNext
正在循环数据。然而,在这一层之下,驱动程序实际上正在请求和接收批量结果。当您执行
getNext
时,驱动程序将无缝地为您获取下一批。您可以控制批量大小。文档中的详细信息应该有助于澄清发生了什么。
在第二个示例中,如果达到 10,然后
break
,则会产生两个副作用:$cursor
中缓存了更多数据。当 $cursor 超出范围时,此缓存将消失。在大多数情况下,这些副作用“没什么大不了的”。但是,如果您在单个进程中执行大量此类处理,您将需要“清理”以避免光标徘徊。
This is not 100% true.
When you do the
foreach
, you're basically issuing a series ofhasNext
/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:$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.