我在MongoDB上运行一个简单的Django应用程序,最近升级到PyMongo 3.0.2 - 但运行速度非常慢。如果我降级到PyMongo 2.8.1或2.7.2,它会再次加速。 MongoDB 3和2.6都会发生这种情况,所以我认为基本的东西已经发生了变化。根据更改日志,PyMongo 3实际上应该加速很多,我找不到任何会导致性能下降的明显变化。我在SO或Google上找不到任何相关问题。这是在Django 1.6.4和Python 2.7.5上。
很难建立一个这样的代码示例,但是我们使用的是单个MongoDB实例(没有分片,没有远程主机),并且在我们使用mongo_client
的每个方法中,我们调用{ {1}}在方法的最后。如果我们不断关闭连接,是否有一些新的连接重新打开行为可能会减慢客户端的速度?示例方法如下:
close()
更新1:
根据建议,我使用 from pymongo import MongoClient
mongo_client = MongoClient()
collection = mongo_client[self._db_prefix + 'assessment']['Assessment']
if collection.find({'itemIds': str(item_id)}).count() != 0:
raise errors.IllegalState('this Item is being used in one or more Assessments')
collection = mongo_client[self._db_prefix + 'assessment']['Item']
item_map = collection.find_one({'_id': ObjectId(item_id.get_identifier())})
if item_map is None:
raise errors.NotFound()
objects.Item(item_map, db_prefix=self._db_prefix, runtime=self._runtime)._delete()
delete_result = collection.delete_one({'_id': ObjectId(item_id.get_identifier())})
if delete_result.deleted_count == 0:
raise errors.NotFound()
mongo_client.close()
库创建了专用负载测试。使用PyMongo 3.0.2:
timeit
实际上会抛出错误:
timeit.timeit('MongoClient()["test_blah"]["blah"].insert_one({"foo":"bar"})', number=10000, setup="from pymongo import MongoClient")
然后我降级到PyMongo 2.8.1:
File "~/Documents/virtual_environments/assessments/lib/python2.7/site-packages/pymongo/pool.py", line 58, in _raise_connection_failure
raise AutoReconnect(msg)
AutoReconnect: localhost:27017: [Errno 49] Can't assign requested address
在python shell中运行相同的命令:
pip install pymongo==2.8.1
这次它实际上已经结束......所以看起来新的timeit.timeit('MongoClient()["test_blah"]["blah"].insert({"foo":"bar"})', number=10000, setup="from pymongo import MongoClient")
8.372910976409912
方法做了不同的事情,它没有关闭连接?
更新2(使用解决方案):
伯尼的回答帮助我们指明了正确的方向,以及SO question。除了使用单个insert_one
之外,我们的问题是我们在每个方法结束时关闭了连接。下面的示例MongoClient()
(PyMongo 3.0.2):
timeit
手动关闭客户端是性能杀手......慢1000倍。也许是由于监控线程缓慢关闭引起的,伯尼提到了什么?
答案 0 :(得分:2)
我认为你看到的问题是由于MongoClient产生了一个后台监控线程。这是PyMongo 3.0中的新功能,与PyMongo 2.x中MongoReplicaSetClient的行为相匹配。你应该能够通过只产生一个MongoClient实例来加快速度(这是使用MongoClient的首选方法)。
>>> import timeit
>>> timeit.timeit('client["test_blah"]["blah"].insert_one({"foo":"bar"})', number=10000, setup="from pymongo import MongoClient; client = MongoClient()")
2.2610740661621094
>>> import pymongo
>>> pymongo.version
'3.0.2'
>>> timeit.timeit('client["test_blah"]["blah"].insert({"foo":"bar"})', number=10000, setup="from pymongo import MongoClient; client = MongoClient()")
2.3010458946228027
>>> import pymongo
>>> pymongo.version
'2.8.1'
我还认为监视器线程关闭时间太长,并且正在寻找修复程序。