2016-07-28 157 views
0

我有超過100000個更新查詢需要執行,db.collection_name.update(upsert=True)只能執行一個查詢語句,如果我逐個執行所有查詢,速度太慢。如何在pymongo中執行一次多個更新查詢?

有什麼辦法可以將多個查詢收集到列表中然後在pymongo中執行一次?

我嘗試使用bulk,並且它不保存任何時候,還沒有一個交易操作:(

這裏是我的代碼片段:

bulk = self._db.initialize_unordered_bulk_op() 
for user_id, result in results.items(): 
    time_stamp = time.strftime('%Y-%m-%d:%H:%M:%S') 
    history = { 
     'create_at': time_stamp, 
     'results': result 
    } 
    bulk.find({'user_id': user_id}).update(
     {'$set': {'update_at': time_stamp}} 
    ) 
    bulk.find({'user_id': user_id}).update(
     {'$addToSet': {'history': history}} 
    ) 
bulk.execute() 

這幾乎是相同的速度下更新聲明:

self._db.update(
    {'user_id': user_id}, 
    {'$set': {'update_at':time.strftime('%Y-%m-%d:%H:%M:%S')}}, 
    upsert=True 
) 
self._db.update(
    {'user_id': user_id}, 
    {'$addToSet': {'history': history}}, 
    upsert=True 
) 

回答

0

您可以引入一個計數器變量,以確保批量發送更新,因爲寫入命令最多隻能接受1000個操作,因此需要將操作分組以便最多進行1000次操作,並在循環達到1000次迭代時重新初始化批量操作。另外,DRY(不要重複自己):將更新語句$set$addToSet合併到一個更新文檔中。您的最終更新腳本應該表現得更好:

bulk = self._db.initialize_unordered_bulk_op() 
counter = 0; 

for user_id, result in results.items(): 
    time_stamp = time.strftime('%Y-%m-%d:%H:%M:%S') 
    history = { 
     'create_at': time_stamp, 
     'results': result 
    } 
    bulk.find({'user_id': user_id}).update({ 
     '$set': { 'update_at': time_stamp }, 
     '$addToSet': { 'history': history } 
    }) 
    counter++ 

    if (counter % 1000 == 0): 
     bulk.execute() 
     bulk = self._db.initialize_unordered_bulk_op() 

if (counter % 1000 != 0): 
    bulk.execute() 
+0

感謝您的DRY提案!我只是沒有意識到可以合併更新語句。而且我也嘗試了你的批量建議,它不能用於節省時間,不幸的是幾乎相同。即使它有效,那麼由於更新批量仍然一個一個地執行,它也不夠優雅,如果我有1000萬更新,該怎麼辦?有沒有任何方法來傳遞一組查詢語句作爲更新參數? – Euryugasaki

+0

您可能錯過了批量更新的觀點;而不是將每個更新請求發送到服務器,大容量每1000次操作發送一次,因此沒有更好的性能。由於上述原因,使用批量API更有效。嘗試做一個合成的微基準測試,更新1000條記錄,而不使用批量API。使用Bulk API,您可以每秒執行大約4000次操作,並且更新10,000,000個文檔(每秒大約5000次操作),只要操作類別相同,就可以大量進行操作。 – chridam

+0

那麼,下面是基準測試的一些有趣結果(使用time.clock() - start):執行預處理:147.572841 self._db.update()的更新時間:5.057265 Bulk.find()的更新時間。 update():0.736898 Total:153.379147輸出顯示同一時間的批量。但是,但是,我沒有觀察到加速度!當我使用秒錶記錄每個輸出內容出現時的實際時間時:執行預處理:2分27秒更新self._db.update()的時間:1分33秒更新bulk.find()的時間。更新():2分18秒這是怎麼回事?爲什麼更新聲明時間結果不匹配? – Euryugasaki