MongoDB count могут сильно замедлить API

Опубликовано 23 September 2016 в Разное

Иногда команда фронтенда или другие потребители API просят выводить в ручках общее число объектов. Если в качестве хранилища используется MongoDB, постарайтесь избежать этого. Такое поведение ручек может значительно их замедлить.

Я говорю о тех случаях, когда ответ API похож на тот, что расположен ниже, то ждите беды.

{
  "total": XX,
  "limit": ZZ,
  "offset": YY,
  "objects": [...]
}

Если коллекция достаточно большая, а запрос достаточно тяжелый, count будет работать непозволительно долго. Запрос find при этом может работать быстро: ему ведь надо вернуть всего-то с десяток объектов. Count будет шерстить весь набор объектов, подходящих под условия запроса.

Иногда добавление дополнительных условий в запрос, которые должны замедлить запрос (к примеру, поиск по регулярному выражению), но при этом сильно сокращают количество подходящих объектов, может даже ускорить ответ от API. Find так и будет возвращать с десяток объектов, а count будет пробегать гораздо меньше объектов.

Так какие же есть решения?

Во первых, если есть возможность поменять формат API, меняйте. Результат со ссылками на предыдущие и следующие результаты (как это делает Facebook API) может оказаться значительно быстрее.

{
  "pre": "link-to-previous-x-objects",
  "next": "link-to-next-x-objects",
  "limit": x,
  "objects": [...]
}

Второй возможных вариант: кэшировать total. Тогда API будет работать примерно как работают поисковые системы: иногда говорить клиенту, что в базе есть больше объектов, чем на самом деле. Во многих случаях это нормально. Особенно когда консистентность весьма условная.

В любом случае, все это имеет значение, если коллекция достаточно большая, объекты приличного размера, а запрос довольно сложный. Во всех остальных случаях, можно делать все, что заблагорассудится. Стоит только не забывать, что сервис может вырасти, а переделывать API потом будет очень сложно и дорого.

---
Возник вопрос? Мне всегда можно написать в Twitter: avkorablev