如果使用Python做大型海量数据批量任务时,并且backend用mongodb做数据储存时,常常面临大量读写数据库的情况。尤其是大量更新任务,由于不能批量操作,我们知道pymongo是同步任务机制,相当耗时。

​ 如果采用多线程、多进程的方案确实有效,但编写麻烦、消耗系统资源大(pymongo还不允许fork线程中共用连接)。这里主要瓶颈在于IO,使用单线程异步操作就会效果很好。
Motor是一个异步mongodb driver,支持异步读写mongodb。它通常用在基于Tornado的异步web服务器中。

我们来测试一下效率,使用传统pymongo来进行批量读写 mongo_test.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
host = '127.0.0.1'
port = 27017
database = 'LiePin'

import time

start = time.clock()

from pymongo import MongoClient

connection = MongoClient(
host,
port
)
db = connection[database]

for doc in db.LiePin_Analysis1.find({}, ['_id', 'JobTitle', 'is_end']):
db.LiePin_Analysis1.update_one({'_id': doc.get('_id')}, {
'$set': {
'is_end': 1
}
})

elapsed = (time.clock() - start)
print("Time used:",elapsed)

运行一下,发现用了4秒左右

再使用motor以异步的形式来编写脚本motor_test.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
主机= '127.0.0.1' 
端口= 27017
数据库= '劣品'

进口时间

开始= 时间。时钟()

从电机导入asyncio
。motor_asyncio 导入AsyncIOMotorClient

connection = AsyncIOMotorClient (
host ,
港口

db = connection [ 数据库]

异步DEF 运行():
异步用于文档的数据库。LiePin_Analysis1 。找到({},[ '_id''JOBTITLE''is_end' ]):
分贝。LiePin_Analysis1 。update_one ({ '_id' :DOC ,得到('_id' )},{ '$集' :{ 'is_end'0 }})

asyncio 。get_event_loop ()。run_until_complete (run ())

经过= (时间,时钟()- 启动)打印(“使用时间” ,经过)

仅仅1秒左右就完成了任务

效率由此可见一般