非常慢的MongoCursor :: next()性能

时间:2013-08-02 13:54:51

标签: php performance mongodb

在某些情况下,我遇到了极慢MongoCursor的表现。

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

TEST1:

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

经过时间:41.78210秒[ 24 ops / s ]

TEST2:

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

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

TEST3:

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

经过时间:0.65439秒[ 1 528 op / s ]

test1 中,无论limit(2)还是limit(200)脚本是否总是24次操作,

我测试了它:

  • mongo v2.4.5

  • php驱动程序1.4.0dev和1.5.0dev

  • Debian 6.0.7和Ubuntu 12.10

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

EDIT1:

我通过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(WARN):杀死未完成的光标63182808988603511
  • 1375693731.5352 - IO(FINE):得到回复
  • 1375693731.5353 - IO(精细):获取光标标题
  • 1375693731.5726 - IO(精细):获取光标主体
  • 1375693731.5727 - IO(WARN):杀死未完成的光标63182981334616260
  • ...

test2:(限制(1),限制(0)且无限制)

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

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

EDIT2:

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

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

mongodb.log:限制(N)

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

mongodb.log: limit(1)

  • Mon Aug 5 14:45:54.899 [conn3] runQuery名为mydb.mycollection {}
  • Mon Aug 5 14:45:54.899 [conn3] query mydb.mycollection ntoreturn:1 ntoskip:0 nscanned:1 keyUpdates:0 locks(micros)r:39 nreturned:1 reslen:53 0ms
  • Mon Aug 5 14:45:54.899 [conn3] runQuery名为mydb.mycollection {}
  • Mon Aug 5 14:45:54.899 [conn3] query mydb.mycollection ntoreturn:1 ntoskip:0 nscanned:1 keyUpdates:0 locks(micros)r:35 nreturned:1 reslen:53 0ms

1 个答案:

答案 0 :(得分: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

撰写了大量有关此内容的文章

现在关于杀死光标仍然是一个谜,37ms慢下来的地方。也许您可以查看您的mongodb.log文件是否有任何见解? (如果我看到这些信息,我会再次更新答案)