2014-08-28 2 views
1

У меня есть база данных mongodb с 10-15 миллионами записей. Для каждого из них я должен обновить поле, которое изначально не существует. Предполагая, что приложение потерпело крах из-за неожиданного завершения работы сервера, как лучше всего обновлять оставшиеся записи?

Должен ли я использовать field: {$exists: false} и обновлять их, или я должен пройти через всю коллекцию и проверять каждый документ, если он имеет это поле, или нет, и если да, выполните обновление? Я беру на себя это потому, что, поскольку вы не можете связать индекс с существованием поля, $ существует, в основном то же самое. Какой из них будет быстрее и почему?

Обратите внимание, что значение, которое это поле будет иметь, зависит от других полей документа, поэтому я не могу выполнить обновление с несколькими: истинными.

Решение: Как @DhruvPathak и @Sammaye предполагают, в то время как показатели, связанные с данными, а не сами поля (так что вы не можете иметь индекс связан с существованием поля), $ существуют могут воспользоваться индексов на документах, где существуют поля, и это значительно увеличивает скорость.

Дополнительная информация: Хотя это немного побочный квест, теперь я знаю причину, по которой приложение разбилось. Сервер вычеркнул курсор, потому что он использовался слишком долго (учитывая размер коллекции). Этого можно избежать, используя batch_size, как описано here.

+0

[пояснить()] (http://docs.mongodb.org/manual/reference/method/cursor.explain/) может помочь – soulcheck

+1

Вы можете добавить поле "field_exists" в свои документы, по умолчанию значение false. Если вы обновите документ, вы установите для параметра «field_exists» значение true. И вы можете легко создать индекс над этим полем. – thomas

+0

@soulcheck Правда, объяснение поможет с запросом $ exist, но в другом случае, когда я обновляю каждое поле вручную, объясните, что не могу дать мне данные о том, насколько эффективен мой цикл при обновлении каждого документа. Это скрипт pymongo. – thehousedude

ответ

1

Да, вы правы, в обоих случаях mongodb будет итерировать по всему набору. Другим хорошим способом для этого было бы создать индекс в этом поле, использовать оператор $exists для выбора целевых, а затем отбросить индекс. Убедитесь, что созданный индекс не является разреженным, так как он не поможет в случае $ exist. http://docs.mongodb.org/manual/core/index-sparse/

+0

Спасибо. Поле, о котором идет речь, является целым числом, поэтому я думаю, что восходящий индекс будет работать нормально? – thehousedude

+1

Создание индекса, а затем его удаление добавят дополнительные служебные данные. – vmr

1

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

2

Мой взгляд на это, что, так как вы не можете связать индекс с существованием поля

Acccording к MongoDB 2.6 теперь может:

> use f 
switched to db f 
> db.t.insert({a:1}) 
WriteResult({ "nInserted" : 1 }) 
> db.t.ensureIndex({b:1}) 
{ 
     "createdCollectionAutomatically" : false, 
     "numIndexesBefore" : 1, 
     "numIndexesAfter" : 2, 
     "ok" : 1 
} 
> db.t.find({b:{$exists:false}}) 
{ "_id" : ObjectId("53e88a7dde0848171584d296"), "a" : 1 } 
> db.t.find({b:{$exists:false}}).explain() 
{ 
     "cursor" : "BtreeCursor b_1", 
     "isMultiKey" : false, 
     "n" : 1, 
     "nscannedObjects" : 1, 
     "nscanned" : 1, 
     "nscannedObjectsAllPlans" : 1, 
     "nscannedAllPlans" : 1, 
     "scanAndOrder" : false, 
     "indexOnly" : false, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "millis" : 0, 
     "indexBounds" : { 
       "b" : [ 
         [ 
           null, 
           null 
         ] 
       ] 
     }, 
     "server" : "ubuntu:27017", 
     "filterSet" : false 
} 
> 

из что я могу найти, это похоже на то, что было добавлено по состоянию на v2.0: https://stackoverflow.com/a/7503114/383478, к сожалению, ссылка doc в этом ответе с тех пор умерла.

Так что запрос явно быстрее с учетом этого, если вы не можете иметь версию до версии 2.0.

+0

Спасибо, я не знал. Хотя это, кажется, восходящий индекс. Из других вопросов, которые я нашел, люди хотели связать индекс с фактическим существованием поля, а не его значением. Это хорошо, хотя он тоже может использовать этот. – thehousedude

+1

@thehousedude это, конечно, было бы лучше для ключевых магазинов значений, mongodb оценивает http://rocksdb.org/ от того, что я недавно использовал в своей JIRA. Это одна из причин, по которым они создают подключаемый механизм хранения, чтобы они могли дать вам такие вещи, как вы можете получить в других технологиях, таких как MySQL и т. Д. – Sammaye

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