MongoDB - слишком много данных для sort() без ошибки индекса

Я использую MongoDB 1.6.3, для хранения большой коллекции (более 300 тыс. Записей). Я добавил составной индекс.

db['collection_name'].getIndexes()
[
    {
        "name" : "_id_",
        "ns" : "db_name.event_logs",
        "key" : {
            "_id" : 1
        }
    },
    {
        "key" : {
            "updated_at.t" : -1,
            "community_id" : 1
        },
        "ns" : "db_name.event_logs",
        "background" : true,
        "name" : "updated_at.t_-1_community_id_1"
    }
]

Тем не менее, когда я пытаюсь запустить этот код:

db['collection_name']
  .find({:community_id => 1})
  .sort(['updated_at.t', -1])
  .skip(@skip)
  .limit(@limit)

Я получаю:

Mongo:: OperationFailure (слишком много данных для sort() без индекса. Добавить индекс или указать меньший предел)

Что я делаю неправильно?

4 ответа

Попробуйте добавить {community_id: 1, 'updated_at.t': -1} индекс. Нужно искать по community_id сначала и потом сортируй.

Таким образом, вы чувствуете, что используете индекс, но на самом деле индекс является составным. Я не уверен, что сортировка "достаточно умна", чтобы использовать только частичный индекс.

Итак, две проблемы:

  1. Исходя из вашего запроса, я бы назвал community_id первой частью индекса, а не второй. updated_at.t звучит как поле, по которому вы будете выполнять запросы диапазона. Индексы работают лучше, если запрос диапазона является вторым битом.
  2. Сколько записей вернется из community_id => 1? Если число не велико, вам, возможно, удастся просто отсортировать без индекса.

Таким образом, вам, возможно, придется изменить индекс, и вам, возможно, придется изменить сортировку, чтобы использовать оба community_id а также updated_at.t, Я знаю, что это кажется излишним, но начните там и проверьте Группы Google, если это все еще не работает.

Даже с индексом, я думаю, вы все равно можете получить эту ошибку, если ваш набор результатов превышает 4 МБ.

Вы можете увидеть размер, зайдя в консоль mongodb и выполнив это:

show dbs
# pick yours (e.g., production)
use db-production
db.articles.stats()

Я закончил с результатами, как это:

{
"ns" : "mdalert-production.encounters",
"count" : 89077,
"size" : 62974416,
"avgObjSize" : 706.9660630690302,
"storageSize" : 85170176,
"numExtents" : 8,
"nindexes" : 6,
"lastExtentSize" : 25819648,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 18808832,
"indexSizes" : {
    "_id_" : 3719168,
    "patient_num_1" : 3440640,
    "msg_timestamp_1" : 2981888,
    "practice_id_1" : 2342912,
    "patient_id_1" : 3342336,
    "msg_timestamp_-1" : 2981888
},
"ok" : 1
}

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

Другие вопросы по тегам