2012-05-31 2 views
0

В настоящее время у меня есть длительная операция (работает в Python + Celery), которая проходит через всю коллекцию Mongo, насчитывающую около 43 000 000 элементов, и анализирует элементы без внесения каких-либо изменений в эти элементы ,Коллекция Split Mongo (по индексу)

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

Я хотел бы разделить эту операцию на несколько небольших операций - возможно, всего на несколько миллионов элементов - и мне интересно, как лучше всего создавать запросы, которые будут выполнять расщепление. У меня есть только один индекс в этой коллекции и его номер _id.

Очевидный ответ, казалось, что-то вроде:

# This is executed in parallel on different servers 
def doAnalysis(skipped,limit) 
    db.<collection>.find().skip(skipped).limit(limit) 

... 

# This is the parent task 
elemsToAnalyze = db.<collection>.find().count()/10; 
for i in range(0,10: 
    doAnalysis(elemsToAnalyze * i, elemsToAnalyze) 

Но оказывается, что .skip() занимает время долго - в основном только до тех пор, как на самом деле выполнения анализа! Есть лучший способ сделать это?

ответ

1

skip() может быть очень медленным в этом случае. Вместо этого вы можете использовать запросы диапазона, используя последний пакет _id пакета для запроса следующей партии. Что-то вроде этого:

db.<collection>.find({ "_id" : { $gte: prev_batch_last_id } }).sort({ _id : 1 }).limit(limit); 

Вам нужно будет сохранить последний идентификатор партии в переменной самостоятельно.

+0

благодарит за ваш ответ. Проблема с этим методом заключается в том, что мне нужно знать last_id из * ранее выполненной * партии. Предпочтительно, я хотел бы иметь возможность запускать эти процессы независимо друг от друга, так что им не нужно было бы делиться данными - преимущество было бы в том, что они будут распараллеливаться. –

+0

Является ли эта коллекция очерченной? Если это так, вы можете использовать ограничения фрагмента как способ разделения коллекции. Если нет, существуют другие способы разделения диапазона _id в вашей коллекции. – matulef

+0

@ChrisW Основываясь на вашем образце conde, я думал, что параллельная обработка не нужна. У вас есть несколько баз данных? Если вы это сделаете, как упомянуто в названии matulef, вы можете использовать границы осколков (если их очертить). Если задача, которую вы выполняете для каждого элемента, очень коротка, выполнение запросов параллельно для одного db не может ускорить обработку вообще, поскольку db может обрабатывать только один запрос за раз. Вы можете сначала попробовать (вручную), если параллельный путь действительно быстрее или нет. – Lycha

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