2012-10-09 219 views
3

我遇到了用于我的python脚本迭代数据集所花费的时间的问题。数据集约为40k文件。这足以导致pymongo游标发出多个内部并从开发者处抽象出来的提取。我尽可能简化我的脚本以示范问题:pymongo光标getMore需要很长时间

from pymongo import Connection 
import time 

def main(): 
    starttime = time.time() 
    cursor = db.survey_answers.find() 
    counter=0; 
    lastsecond=-1; 
    for entry in cursor: 
     if int(time.time()-starttime)!=lastsecond: 
      print "loop number:", counter, " seconds:",int(time.time()-starttime); 
      lastsecond= int(time.time()-starttime) 
     counter+=1; 
    print (time.time()-starttime), "seconds for the mongo query to get rows:",counter; 

connection = Connection(APPSERVER)#either localhost or hostname depending on test 
db = connection.beacon 

if __name__ == "__main__": 
    main() 

我的设置如下。我有4个独立的主机,一个APPSERVER运行mongos,以及3个其他分区主机,每个分区主副本集和其他两个主副副本集。

我可以从碎片服务器(带有指向APPSERVER主机的连接)的一个运行此,我也得到:

loop number: 0 seconds: 0 
loop number: 101 seconds: 2 
loop number: 7343 seconds: 5 
loop number: 14666 seconds: 8 
loop number: 21810 seconds: 10 
loop number: 28985 seconds: 13 
loop number: 36078 seconds: 15 
16.0257680416 seconds for the mongo query to get rows: 41541 

所以,很明显这是怎么回事就在这里,游标请求的第一BATCHSIZE是100,然后每个后续的一个是价值4米的数据,这对我来说似乎超过了7k个文件。每次获取成本为2-3秒!!!!

我想我可以通过移动我的应用程序更接近mongos实例来解决这个问题。我在APPSERVER上运行上面的代码(连接指向本地主机),希望减少网络使用情况......但情况更糟!

loop number: 0 seconds: 0 
loop number: 101 seconds: 9 
loop number: 7343 seconds: 19 
loop number: 14666 seconds: 28 
loop number: 21810 seconds: 38 
loop number: 28985 seconds: 47 
loop number: 36078 seconds: 53 
53.5974030495 seconds for the mongo query to get rows: 41541 

光标大小正是在两个测试,这是很好的相同,但每个光标这里获取成本9-10秒!

我知道我有四个独立的主机需要沟通,所以这不能是即时的。但是我需要遍历大概10m记录的集合。在每7k 2秒的时间内,这需要只需一小时!我不能有这个!

顺便说一句,我是新来的蟒蛇/蒙戈的世界里,我已经习惯了PHP和MySQL,我希望它可以在几分之一秒内处理:

$q=mysql_query("select * from big_table");//let's say 10m rows here .... 
$c=0; 
while($r=mysql_fetch_rows($q)) 
    $c++; 
echo $c." rows examined"; 

有人可以解释我提出的pymongo(〜1小时)和php/mysql(< 1秒)方法之间的巨大差异?谢谢!

+1

我的所有主机都是ec2实例,所以网络延迟不是问题,从APPSERVER ping分片服务器需要0.400ms – Landon

+0

这些40k文档的平均大小是多少? – JohnnyHK

+0

该集合上的stat()显示:'“avgObjSize”:835.3698755446427,' – Landon

回答

3

我能够在A. Jesse Jiryu Davis的帮助下解决这个问题。原来我没有安装C扩展。我想在没有碎片的情况下运行另一个测试,因此我可以排除网络延迟问题。我找到了一个干净的主机,设置了mongo,导入了我的数据,然后运行我的脚本,花费了相同的时间。所以我知道分片/副本集与这个问题没有任何关系。

修复之前,我是能够打印:

pymongo.has_c(): False 
pymongo version 2.3 

然后我跟着instructions安装依赖于C扩展:

yum install gcc python-devel 

然后我重新安装了pymongo司机:

git clone git://github.com/mongodb/mongo-python-driver.git pymongo 
cd pymongo/ 
python setup.py install 

我重新执行了我的脚本,现在可以打印:

pymongo.has_c(): True 
pymongo version 2.3+ 

大约需要1.8秒来运行,而不是上面的16。获取4万条记录并重复它们仍然很长,但这是一个重大改进。

我现在将在我的prod(sharded,replica set)环境中运行这些更新,希望看到相同的结果。

**更新* * 我更新了我的督促环境我pymongo司机并有改善,虽然不及。在几次测试中花费了大约2.5-3.5秒。我认为这里的分拆性是错误的。迭代4万条记录似乎仍然非常缓慢。

+1

除了“似乎很慢”以外,您是否可以将PyMongo的性能与同一环境中相同任务的Java或PHP驱动程序进行比较? –