Медленная разбивка на несколько тонн записей в mongodb
У меня более 300 тыс. записей в одной коллекции в Монго.
Когда я запускаю этот очень простой запрос:
db.myCollection.find().limit(5);
Требуется всего несколько миллисекунд.
Но когда я использую пропустить в запросе:
db.myCollection.find().skip(200000).limit(5)
Он ничего не вернет... он запускается в течение нескольких минут и ничего не возвращает.
Как сделать это лучше?
Ответы
Ответ 1
От MongoDB документация:
Пейджинговые затраты
К сожалению, пропуск может быть (очень) дорогостоящим и требует, чтобы сервер шел от начала коллекции или индекса, чтобы перейти в позицию смещения/пропуска, прежде чем он сможет начать возвращать страницу данных (ограничение). По мере увеличения количества страниц пропуск будет медленнее и интенсивнее процессора, и, возможно, IO привязан, с большими коллекциями.
Подкачка на основе диапазона обеспечивает лучшее использование индексов, но не позволяет вам легко перейти на определенную страницу.
Вы должны задать себе вопрос: как часто вам нужна 40000-я страница? Также см. эту статью;
Ответ 2
Один подход к этой проблеме, если у вас есть большое количество документов, и вы показываете их в отсортированном порядке (я не уверен, насколько полезен skip
, если вы не знаете), будет использовать ключ, повторно сортировка, чтобы выбрать следующую страницу результатов.
Итак, если вы начинаете с
db.myCollection.find().limit(100).sort(created_date:true);
а затем извлечение созданной даты последнего документа, возвращаемого курсором, в переменную max_created_date_from_last_result
, вы можете получить следующую страницу с гораздо более эффективным (предположим, у вас есть индекс на created_date
) запрос
db.myCollection.find({created_date : { $gt : max_created_date_from_last_result } }).limit(100).sort(created_date:true);