2016-09-23 22 views
6

Używam pymongo do aktualizacji zbiorczej.
Lista nazwisk poniżej jest odrębna lista nazw (każda nazwa może mieć mutiple dokumentów w kolekcji)Aktualizacja zbiorcza jest zbyt powolna.

Kod 1:

bulk = db.collection.initialize_unordered_bulk_op() 
for name in names: 
    bulk.find({"A":{"$exists":False},'Name':name}).update({"$set":{'B':b,'C':c,'D':d}}) 
print bulk.execute() 

Kod 2:

bulk = db.collection.initialize_unordered_bulk_op() 
counter = 0 
for name in names: 
    bulk.find({"A":{"$exists":False},'Name':name}).update({"$set":{'B':b,'C':c,'D':d}}) 
    counter =counter + 1 
    if (counter % 100 == 0): 
     print bulk.execute() 
     bulk = db.collection.initialize_unordered_bulk_op() 
if (counter % 100 != 0): 
    print bulk.execute() 

Mam 50000 dokumentów w mojej kolekcji. Jeśli pozbędę się licznika i instrukcji (kod 1), kod utknie! W przypadku instrukcji if (Code 2) zakładam, że operacja ta nie powinna zająć więcej niż kilka minut, ale zajmuje więcej niż to! Czy możesz mi pomóc szybciej to zrobić, czy nie mam racji w moim założeniu ?!

Odpowiedz

6

Najprawdopodobniej zapomniałeś dodać indeksów do obsługi zapytań! Spowoduje to uruchomienie pełnych skanów kolekcji dla każdej operacji, która jest nudna powoli (jak sobie uświadomiłeś).

Poniższy kod testuje za pomocą update_many, a większość bez indeksu i z indeksami w polu "name" i "A". Liczby, które otrzymasz, mówią same za siebie.

Uwaga, nie byłem wystarczająco namiętny, aby zrobić to dla 50000 bez indeksów, ale dla 10000 dokumentów. wyników dla 10000 są:

  • bez indeksu i update_many: 38,6 sekund
  • bez indeksu i masie aktualizacji: 28,7 sekund
  • o indeksie i update_many: 3,9 sek
  • o indeksie i objętościowego działka 0,52 sekund

Dla 50000 dokumentów z dodanym indeksem zajmuje 2,67 sekundy. Uruchomiłem test na komputerze z systemem Windows i uruchomiłem mongo na tym samym hoście w oknie dokowanym.

Aby uzyskać więcej informacji o indeksach, zobacz https://docs.mongodb.com/manual/indexes/#indexes. W skrócie: Indeksy są przechowywane w pamięci RAM i pozwalają na szybkie wyszukiwanie i wyszukiwanie dokumentów. Indeksy muszą w szczególności odpowiadać Twoim zapytaniom.

from pymongo import MongoClient 
import random 
from timeit import timeit 


col = MongoClient()['test']['test'] 

col.drop() # erase all documents in collection 'test' 
docs = [] 

# initialize 10000 documents use a random number between 0 and 1 converted 
# to a string as name. For the documents with a name > 0.5 add the key A 
for i in range(0, 10000): 
    number = random.random() 
    if number > 0.5: 
     doc = {'name': str(number), 
     'A': True} 
    else: 
     doc = {'name': str(number)} 
    docs.append(doc) 

col.insert_many(docs) # insert all documents into the collection 
names = col.distinct('name') # get all distinct values for the key name from the collection 


def update_with_update_many(): 
    for name in names: 
     col.update_many({'A': {'$exists': False}, 'Name': name}, 
         {'$set': {'B': 1, 'C': 2, 'D': 3}}) 

def update_with_bulk(): 
    bulk = col.initialize_unordered_bulk_op() 
    for name in names: 
     bulk.find({'A': {'$exists': False}, 'Name': name}).\ 
      update({'$set': {'B': 1, 'C': 2, 'D': 3}}) 
    bulk.execute() 

print(timeit(update_with_update_many, number=1)) 
print(timeit(update_with_bulk, number=1)) 
col.create_index('A') # this adds an index on key A 
col.create_index('Name') # this adds an index on key Name 
print(timeit(update_with_update_many, number=1)) 
print(timeit(update_with_bulk, number=1)) 
+0

Dzięki za pomoc, ale myślę, że czasy, które zostały podane powyżej nie są prawidłowe, ponieważ nie są do 10000 dokumentów, ale tylko połowa z nich (biorąc pod uwagę> 0,5 <= 0,5 są jednakowo prawdopodobny). Pomogłoby to również, gdybyś mógł pokazać, jak indeksowałeś pola A i imię dla początkującego. Dzięki jeszcze raz! – amazingCodingExperience

+0

Ponadto, w jaki sposób indeksowanie umocni proces? Czy możesz podzielić się teorią za tym? – amazingCodingExperience

+0

Dodano więcej informacji do mojej odpowiedzi. Jednak mongodb oferuje całkiem dobre kursy online za darmo: https://university.mongodb.com/courses/M101P/about Proponuję wziąć jeden z nich, aby przyspieszyć z mongo. – squanto773