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

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

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 байта

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


person sheetal_158    schedule 19.11.2014    source источник


Ответы (6)


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

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

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

person A. Jesse Jiryu Davis    schedule 19.11.2014
comment
можем ли мы изменить этот предел? - person kumarharsh; 21.07.2015
comment
Лучше объявить индекс, чтобы вам не нужно было сортировать в ОЗУ: быстрее и надежнее, ограниченное использование ОЗУ, а не потенциально неограниченное. Если вы настаиваете, превратите свою находку в агрегацию (которая может использовать 100 МБ ОЗУ для сортировки) и установите параметр allowDiskUse: true, чтобы сообщить платформе агрегации о сбросе на диск, если она превысит 100 МБ ОЗУ. Ожидайте серьезного снижения производительности по сравнению с простым объявлением соответствующего индекса. docs.mongodb.org/manual/reference/operator /агрегация/сортировка/ - person A. Jesse Jiryu Davis; 21.07.2015
comment
О, это, конечно, лучшее решение, и единственно разумное. Мне просто было интересно узнать, как изменить лимит. - person kumarharsh; 22.07.2015
comment
Понял. Лимит не может быть изменен. - person A. Jesse Jiryu Davis; 22.07.2015
comment
На самом деле его можно изменить. Вам нужно запустить эту команду: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Источник: askubuntu.com/questions/501937/ - person kumarharsh; 26.07.2015
comment
Приятно отметить для пользователей мангуста, что установка index:true в опоре в вашей схеме решит эту проблему... мангуст проверит все ваши схемы и перед запуском приложения убедитесь, что поля действительно являются индексами... то есть, если вы отключаете это поведение с помощью mySchema.set('autoIndex', false); - person Benjamin Conant; 26.02.2016
comment
Я создал индекс в поле сортировки, но все же он дает мне эту операцию сортировки, которая использует больше, чем максимальное значение 33554432 байтов ОЗУ. Ошибка может быть связана с тем, что я применяю операцию сопоставления перед сортировкой и в соответствии с документом mongo, если вы используете сопоставление перед операцией сортировки. будет пренебрегать индексом и выполнять сортировку в памяти по всем совпавшим записям. - person Amol Suryawanshi; 19.02.2018
comment
Если это принятый ответ, то он должен включать информацию о том, как добавить индекс. - person Philipp Ludwig; 24.06.2018
comment
Стоит отметить, что вы можете увидеть эту ошибку, если попытаетесь выполнить сортировку по несуществующему полю (например, по опечатке). - person Steven Soroka; 23.04.2019

Как сказал 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+

person JERRY    schedule 16.07.2016
comment
Как установить это ограничение на постоянной основе в файле конфигурации? У меня есть машина с памятью 1 ТБ, предназначенная для монго, и я хотел бы постоянно ее запускать. - person Samantha Atkins; 26.07.2018
comment
@SamanthaAtkins Я обновил ответ, чтобы навсегда установить это в файле конфигурации. - person JERRY; 31.07.2018
comment
@JERRY, где установить постоянно в рельсах. Рельсы 5/mongoid.yml? - person Prateep Kul; 30.03.2019
comment
Я нашел это. запустите на моем терминале: mongod и следуйте руководству zocada.com/setting-mongodb-users -руководство для начинающих - person Prateep Kul; 30.03.2019

решается индексацией

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])
person sheetal_158    schedule 19.11.2014
comment
обязательно не используйте разреженный индекс, они игнорируются, если вы сортируете по каждому документу - person Charly Koza; 23.11.2016
comment
Для версии MongoDB ›= 3 используйте: create_index вместо ensure_index см. здесь: kb.objectrocket.com/mongo-db/ - person Jacob Philpott; 10.02.2021

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

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

(Хотя не уверен, как это сделать в pymongo).

person poroszd    schedule 23.06.2017
comment
В pymongo будет db_handle.aggregate(pipe, allowDiskUse=True). См. этот вопрос для получения дополнительной информации! - person Genarito; 21.03.2020

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

db_handle.ensureIndex({executedDate: 1})
person wytten    schedule 20.03.2018

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

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() } )
person shilovk    schedule 04.04.2017