2016-09-23 1 views
6

Я использую pymongo для массового обновления.
Список имен Ниже приведен отчетливый список имен (каждое имя может иметь Mutiple документы в коллекции)Массовое обновление слишком медленно

Код 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() 

Код 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() 

У меня есть 50000 документов в моей коллекции. Если я избавлюсь от счетчика и если оператор (код 1), код застрянет! С выражением if (код 2), я предполагаю, что эта операция не должна занимать больше двух минут, но она занимает больше места! Не могли бы вы помочь мне сделать это быстрее или я ошибаюсь в своем предположении ?!

ответ

6

Вы, скорее всего, забыли добавить индексы для поддержки своих запросов! Это приведет к полному сканированию коллекции для каждой вашей операции, которая будет скучной медленной (как вы поняли).

Следующий код проверяет использование update_many и объемный материал без индексов и с индексами в поле «имя» и «A». Числа, которые вы получаете, говорят сами за себя.

Замечание. Я не был достаточно страстным, чтобы сделать это за 50000 без индексов, но для 10000 документов. Результаты по 10000 являются:

  • без индекса и update_many: 38,6 секунд
  • без индекса и объемного обновления: 28,7 секунды
  • с индексом и update_many: 3,9 секунды
  • с индексом и объемного обновления: 0,52 секунд

Для 50000 документов с добавленным индексом требуется 2,67 секунды. Я выполнил тест на машине с Windows и mongo, работающей на том же хосте в докере.

Дополнительную информацию об индексах см. https://docs.mongodb.com/manual/indexes/#indexes. Короче: индексы хранятся в ОЗУ и позволяют быстро запрашивать и искать документы. Индексы должны специально выбирать для соответствия вашим запросам.

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

Спасибо за помощь, но я думаю, что тайминги, что вы, приведенные выше, не является правильным, поскольку они не предназначены для 10000 документов, но только половина из них (с учетом> 0,5 и <= 0,5 одинаково вероятно). Кроме того, это поможет, если вы можете поделиться тем, как вы проиндексировали поля A и Name для новичков. Еще раз спасибо! – amazingCodingExperience

+0

Также, как бы индексирование закрепило процесс? Не могли бы вы поделиться теорией? – amazingCodingExperience

+0

Добавил больше информации к моему ответу. Тем не менее, mongodb предлагает неплохие онлайн-курсы бесплатно: https://university.mongodb.com/courses/M101P/about Я предлагаю вам взять один из них, чтобы ускориться с монго. – squanto773

 Смежные вопросы

  • Нет связанных вопросов^_^