Использование буферизованных данных на этапе сортировки переполнения превышает внутренний лимит


85

Используя код:

all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING)
print all_reviews.count()

print all_reviews[0]
print all_reviews[2000000]

Счетчик печатает 2043484, и он печатает all_reviews[0].

Однако при печати all_reviews[2000000]я получаю сообщение об ошибке:

pymongo.errors.OperationFailure: ошибка базы данных: ошибка выполнения: использование буферизованных данных этапа сортировки переполнения 33554495 байтов превышает внутренний предел 33554432 байтов

Как мне с этим справиться?

Ответы:


119

Вы используете ограничение в 32 МБ для сортировки в памяти:

https://docs.mongodb.com/manual/reference/limits/#Sort-Operations

Добавьте индекс в поле сортировки. Это позволяет MongoDB передавать вам документы в отсортированном порядке, а не пытаться загрузить их все в память на сервере и отсортировать их в памяти перед отправкой клиенту.


7
Лучше объявить индекс, чтобы вам не нужно было сортировать в ОЗУ: быстрее и надежнее, с ограниченным использованием ОЗУ, а не потенциально неограниченным. Если вы настаиваете, превратите свой «find» в агрегацию (которая может использовать 100 МБ ОЗУ для сортировки) и установите allowDiskUse: true, чтобы система агрегации передавала данные на диск, если объем ОЗУ превышает 100 МБ. Ожидайте серьезного снижения производительности по сравнению с простым объявлением соответствующего индекса. docs.mongodb.org/manual/reference/operator/aggregation/sort/…
А. Джесси Джирью Дэвис

32
Собственно, это можно изменить. Вы должны выполнить эту команду: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Источник: askubuntu.com/questions/501937/…
kumarharsh

6
Полезно отметить для пользователей мангуста, что установка index: true в опоре в вашей схеме решит эту проблему ... мангуст пройдет через все ваши схемы и убедитесь, что поля на самом деле являются индексами перед запуском приложения ... вы отключаете это поведение с помощью mySchema.set ('autoIndex', false);
Бенджамин Конант,

2
Я создал индекс для поля сортировки, но все же он дает мне эту ошибку «Операция сортировки использует больше, чем максимальное количество 33554432 байтов ОЗУ», может быть из-за того, что я применяю операцию сопоставления перед сортировкой и в соответствии с документом mongo, если вы используете сопоставление перед сортировкой Операция игнорируется индексом и выполняет сортировку в памяти по всем совпадающим записям.
Амол Сурьяванши

11
Если это принятый ответ, он должен включать информацию о том, как добавить индекс.
Филипп Людвиг

46

Как сказано kumar_harshв разделе комментариев, я хотел бы добавить еще один момент.

Вы можете просмотреть текущее использование буфера, используя следующую команду над adminбазой данных:

> use admin
switched to db admin
> db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
{ "internalQueryExecMaxBlockingSortBytes" : 33554432, "ok" : 1 }

Он имеет значение по умолчанию 32 МБ (33554432 байта). В этом случае у вас не хватает данных буфера, поэтому вы можете увеличить лимит буфера с вашим собственным определенным оптимальным значением, например 50 МБ, как показано ниже:

>  db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes:50151432})
{ "was" : 33554432, "ok" : 1 }

Мы также можем установить этот предел навсегда с помощью следующего параметра в файле конфигурации mongodb:

setParameter=internalQueryExecMaxBlockingSortBytes=309715200

Надеюсь это поможет !!!

Note: Эти команды поддерживаются только после версии 3.0 +


Каким образом можно установить это ограничение на постоянной основе в файле конфигурации? У меня есть машина с памятью на 1 ТБ, предназначенная для монго, и я хотел бы постоянно проверять ее.
Саманта Аткинс

@SamanthaAtkins Я обновил ответ, чтобы установить это постоянно в файле конфигурации.
ДЖЕРРИ

@JERRY, куда ставить постоянно в рельсах. Рельсы 5 / mongoid.yml?
Prateep Kul

Я нашел это. запустить на моем терминале с помощью: mongod и следовать руководству zocada.com/setting-mongodb-users-beginners-guide
Kul

24

решено с индексацией

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])

не используйте разреженный индекс, они игнорируются, если вы сортируете каждый документ
Чарли Коза

15

Если вы хотите избежать создания индекса (например, вам просто нужна быстрая проверка для изучения данных), вы можете использовать агрегирование с использованием диска:

all_reviews = db_handle.aggregate([{$sort: {'reviewDate': 1}}], {allowDiskUse: true})

(Хотя не знаю, как это сделать в пимонго).


В пимонго было бы db_handle.aggregate(pipe, allowDiskUse=True). См. Этот вопрос для получения дополнительной информации!
Genarito

3

Синтаксис JavaScript API для индекса:

db_handle.ensureIndex({executedDate: 1})

2

В моем случае нужно было исправить нужные индексы в коде и воссоздать их:

rake db:mongoid:create_indexes RAILS_ENV=production

Поскольку переполнение памяти не происходит при наличии необходимого индекса поля.

PS До этого приходилось отключать ошибки при создании длинных индексов:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )

Также могут понадобиться reIndex:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> use your_db
switched to db your_db
> db.getCollectionNames().forEach( function(collection){ db[collection].reIndex() } )
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.