1

MongoCursor在某些情况下,我面临着极其缓慢的性能。

$mongoClient = new MongoClient('mongodb://127.0.0.1:27017');
$collection = $mc->mydb->mycollection;

测试1:

for($i=0; $i<1000; $i++)
{
    $cursor = $collection->find()->limit(2);
    $cursor->next();
}

经过时间:41.78210 秒 [ 24 次操作/秒]

测试2:

for($i=0; $i<1000; $i++)
{
    $cursor = $collection->find()->limit(1);
    $cursor->next();
}

经过的时间:0.47898 秒 [ 2 088 ops/s ]

测试3:

for($i=0; $i<1000; $i++)
{
    $cursor = $collection->find()->limit(2)->batchSize(-2);
    $cursor->next();
}

经过时间:0.65439 秒 [ 1 528 操作/秒]

test1中,无论脚本limit(2)是否limit(200)始终执行 24 ops/s;

我用以下方法对其进行了测试:

  • 蒙哥 v2.4.5

  • php 驱动程序 1.4.0dev 和 1.5.0dev

  • Debian 6.0.7 和 Ubuntu 12.10

这是php驱动程序中的一些问题吗?

编辑1:

我通过 MongoLog 做了一些记录,得到了有趣的结果:

MongoLog::setLevel(MongoLog::ALL);
MongoLog::setModule(MongoLog::IO);

test1:(限制(N),其中 N > 1)

  • 1375693731.5349 - IO(FINE):得到回复
  • 1375693731.5350 - IO(FINE):获取光标标题
  • 1375693731.5351 - IO(FINE):获取光标主体
  • 1375693731.5351 - IO(警告):杀死未完成的游标 63182808988603511
  • 1375693731.5352 - IO(FINE):得到回复
  • 1375693731.5353 - IO(FINE):获取光标标题
  • 1375693731.5726 - IO(FINE):获取光标主体
  • 1375693731.5727 - IO(警告):杀死未完成的游标 63182981334616260
  • ...

test2: (limit(1), limit(0) 和无限制)

  • 1375693866.2663 - IO(FINE):得到回复
  • 1375693866.2663 - IO(FINE):获取光标标题
  • 1375693866.2663 - IO(FINE):获取光标主体
  • 1375693866.2665 - IO(FINE):得到回复
  • 1375693866.2665 - IO(FINE):获取光标标题
  • 1375693866.2665 - IO(FINE):获取光标主体
  • ...

正如您所看到的,当我使用 N(其中 N>1)驱动程序限制查询时,killing unfinished cursor以及下一次尝试获取光标主体时,它会花费很多时间。

编辑2:

是的,时间只涉及 20 个文档的收集,但是 20K 文档只会影响 limit(0) 和 noLimit,它们会像你说的那样杀死光标。

这是 logLevel:5 的日志。我没有任何线索。

mongodb.log:限制(N)

  • 8 月 5 日星期一 14:43:55.292 [conn3] 查询 mydb.mycollection cursorid:1002459676459826 ntoreturn:2 ntoskip:0 nscanned:3 keyUpdates:0 locks(micros) r:84 nreturned:2 reslen:86 0ms
  • 8 月 5 日星期一 14:43:55.293 [conn3] killcursors: found 1 of 1
  • 8 月 5 日星期一 14:43:55。293 [conn3] killcursors keyUpdates:0 0ms
  • 8 月 5 日星期一 14:43:55。332 [conn3] runQuery 称为 mydb.mycollection {}
  • 8 月 5 日星期一 14:43:55.333 [conn3] 查询 mydb.mycollection cursorid:1002631131988423 ntoreturn:2 ntoskip:0 nscanned:3 keyUpdates:0 locks(micros) r:84 nreturned:2 reslen:86 0ms

mongodb.log:限制(1)

  • 8 月 5 日星期一 14:45:54.899 [conn3] runQuery 称为 mydb.mycollection {}
  • 8 月 5 日星期一 14:45:54.899 [conn3] 查询 mydb.mycollection ntoreturn:1 ntoskip:0 nscanned:1 keyUpdates:0 locks(micros) r:39 nreturned:1 reslen:53 0ms
  • 8 月 5 日星期一 14:45:54.899 [conn3] runQuery 称为 mydb.mycollection {}
  • 8 月 5 日星期一 14:45:54.899 [conn3] 查询 mydb.mycollection ntoreturn:1 ntoskip:0 nscanned:1 keyUpdates:0 locks(micros) r:35 nreturned:1 reslen:53 0ms
4

1 回答 1

2

我不确定您是如何运行此程序的,以及您在我的收藏中有多少项目,但所有三个测试都需要 0.102-0.112 秒 - 无论我有多少项目。比你跑的快得多。这是 PHP 5.4 和驱动程序版本 1.5.0dev。

“杀死未完成的游标”消息是因为您没有读取属于游标指示的结果集的所有找到的数据。我假设您在您的收藏中只有 20 个项目而不是 20k 进行了测试,因为这也会显示消息。

默认情况下,从 MongoDB 读取的第一批是 101 个文档。因此,如果您的结果集小于该值,则没有游标。

limit(1)limit(n)哪里n < 0特别,因为它们的意思是“给我很多abs(n)结果,然后关闭光标”。

limit(0)并且没有给出限制只是意味着“给我默认批次”——初始结果是 101 个文档。我在http://drck.me/mongocur-9f8上写了很多关于这个的文章

现在至于在被杀死的光标后你在哪里减速 37 毫秒仍然是一个谜。也许您可以看看您的mongodb.log文件是否有任何见解?(如果我看到该信息,我会再次更新答案)

于 2013-08-02T14:37:02.433 回答