Використання буферизованих даних етапу сортування переповнення перевищує внутрішній ліміт


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

Як я з цим справляюся?

Відповіді:


118

Ви натрапили на 32 МБ для сортування в пам’яті:

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

Додайте індекс до поля сортування. Це дозволяє MongoDB передавати вам документи в упорядкованому порядку, а не намагатися завантажувати їх усі в пам’ять на сервері та сортувати в пам’яті перед тим, як відправляти їх клієнту.


7
Краще оголосити індекс, щоб не потрібно було сортувати в оперативній пам'яті: швидше і надійніше, обмежене використання оперативної пам'яті, а не потенційно необмежене. Якщо ви наполягаєте, перетворіть свою "знахідку" в агрегацію (яка може використовувати 100 МБ оперативної пам'яті для сортування) і встановіть allowDiskUse: true, щоб сказати структуру агрегування, щоб вона вилилася на диск, якщо вона перевищує 100 МБ оперативної пам'яті. Очікуйте суворого покарання за ефективність порівняно із просто оголошенням відповідного індексу. docs.mongodb.org/manual/reference/operator/aggregation/sort/…
A. Jesse Jiryu Davis

31
Власне, це можна змінити. Ви повинні виконати цю команду: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Джерело: askubuntu.com/questions/501937/…
kumarharsh

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

2
Я створив індекс у полі сортування, але все-таки він видає мені помилку "Операція сортування, що використовується більше, ніж максимальна кількість 33554432 байт оперативної пам'яті", може бути через те, що я застосовую операцію збігу перед сортуванням та згідно з mongo doc, якщо ви використовуєте збіг перед сортуванням операція буде нехтувати індексом і виконуватиме в сортуванні пам'яті всі зіставлені записи.
Амол Сур'яванші

11
Якщо це прийнята відповідь, тоді вона повинна містити інформацію про те, як додати індекс.
Філіп Людвіг,

45

Як сказано 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 ТБ, присвячена mongo, і я хотів би її постійно розкрутити.
Саманта Еткінс

@SamanthaAtkins Я оновив відповідь, щоб назавжди встановити це у файлі конфігурації.
JERRY

@JERRY, де постійно встановлювати в рейки. Рейки 5 / mongoid.yml?
Prateep Kul

Я знайшов це. запустити на моєму терміналі за допомогою: mongod і дотримуватися інструкції zocada.com/setting-mongodb-users-beginners-guide
Пратейп Куль

24

вирішено за допомогою індексації

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

не використовуйте розріджений індекс, вони ігноруються, якщо ви сортуєте кожен документ
Charly Koza

15

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

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

(Хоча не знаю, як це зробити в pymongo).


У пимонго було б 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.