Монго очень медленно считает, когда есть миллионы записей - PullRequest
19 голосов
/ 20 марта 2012
//FAST
db.datasources.find().count()
12036788

//SLOW    
db.datasources.find({nid:19882}).count()
10161684

Индекс по nid

Есть ли способ сделать второй запрос быстрее? (Это занимает около 8 секунд)

Ответы [ 3 ]

26 голосов
/ 20 марта 2012

Количество запросов, проиндексированных или нет, медленное из-за того, что MongoDB все еще должен пройти полное b-дерево, чтобы найти соответствующее количество документов, соответствующих вашим критериям. Причина этого заключается в том, что структура b-дерева MongoDB не «подсчитывается», то есть каждый узел не хранит информацию о количестве элементов в узле / поддереве.

О проблеме сообщается здесь https://jira.mongodb.org/browse/SERVER-1752, и в настоящее время не существует обходного пути для повышения производительности, кроме ручного ведения счетчика для этой коллекции, что, очевидно, имеет несколько недостатков.

Также обратите внимание, что версия db.col.count () (поэтому не имеет критериев) может использовать большое сокращение и фактически не выполняет запрос, следовательно, это скорость. Тем не менее, он не всегда сообщает то же значение, что и запрос подсчета, который должен возвращать все элементы (например, это не будет в изолированных средах с высокой пропускной способностью записи). Для обсуждения, является ли это ошибкой. Я думаю, что это так.

Обратите внимание, что в 2.3+ была введена значительная оптимизация, которая должна (и делает) улучшить производительность подсчетов в индексированных полях. Смотри: https://jira.mongodb.org/browse/SERVER-7745

14 голосов
/ 27 сентября 2015

Как сказал @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, в противном случае я отображаю точное число.

Что касается первого варианта ... Я еще не придумал опрятного решения.

0 голосов
/ 20 марта 2012

Он должен просматривать каждое поле каждого документа на секунду. Вы можете индексировать nid, чтобы ускорить подсчет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...