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


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.