Монго считается очень медленным, когда есть миллионы записей
//FAST
db.datasources.find().count()
12036788
//SLOW
db.datasources.find({nid:19882}).count()
10161684
Индекс по ниду
Как сделать второй запрос быстрее? (Это занимает около 8 секунд)
Ответы
Ответ 1
Количество запросов, индексированных или иным образом, происходит медленно из-за того, что MongoDB все еще должен выполнить полную b-tree walk, чтобы найти соответствующее количество документов, соответствующих вашим критериям. Причиной этого является то, что структура b-tree MongoDB не "подсчитывается", так как каждый node не хранит информацию о количестве элементов в node/поддереве.
Проблема приведена здесь https://jira.mongodb.org/browse/SERVER-1752, и в настоящее время нет обходного пути для повышения производительности, кроме ручного ведения счетчика для этой коллекции, который, очевидно, поставляется с несколькими минусами.
Также обратите внимание, что версия db.col.count() (так что нет критериев) может иметь большой ярлык и фактически не выполняет запрос, следовательно, скорость. При этом он не всегда сообщает о том же значении, что и запрос счетчика, который должен возвращать все элементы (например, он не будет в оштукатуренных средах с высокой пропускной способностью записи). Подумайте о том, есть ли эта ошибка. Я думаю, что это так.
Обратите внимание, что в версии 2.3+ была введена значительная оптимизация, которая должна (и делает) улучшать производительность подсчетов по индексированным полям. См.: https://jira.mongodb.org/browse/SERVER-7745
Ответ 2
Как сказал @Remon, count() должен отсканировать все документы, соответствующие запросу/фильтру. Это O (n), где n - количество документов, которые будут соответствовать индексу, или количество документов в коллекции, если поле не индексировано.
В таких случаях вы, как правило, хотите пересмотреть свое требование. Вам действительно нужно точное число для результата 10161684? Если точность важна, вы должны сохранить отдельный счетчик для конкретного запроса.
Но в большинстве случаев точность не важна. Это один из двух:
- Вам все равно, 10 миллионов или 10,2 миллиона, но порядок имеет важное значение, то есть вы заботитесь о том, 8 миллионов или 10 миллионов.
- Вам нужно только точное число, если оно маленькое. Я., вам интересно узнать, что есть 44 результата или 72. Но как только это выходит за пределы, скажем, 1000, вы можете просто сказать "Более 1000 объектов", найденных пользователю.
В моих приложениях я обнаружил, что второй вариант - это то, что я хочу. Таким образом, я также ограничиваю запрос count(), так что подсчет останавливается, когда он достигает предела. Например:
db.datasources.find({nid: 19882}).limit(1000).count(true)
Для пользователя я показываю "1000 или более найденных результатов", если число равно 1000, в противном случае я показываю точный номер.
Что касается первого варианта... Я еще не думал о аккуратном решении.
Ответ 3
Он должен просматривать каждое поле каждого документа для второго. Вы можете индексировать nid
, чтобы сделать счет быстрее.