Подтвердить что ты не робот

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

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

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() без индекса. добавить индекс или указать меньший предел)

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

Ответ 3

Даже с индексом, я думаю, вы все равно можете получить эту ошибку, если ваш результирующий набор превышает 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
}

Ответ 4

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