Как создать индекс для сложного запроса MongoDB

#mongodb #mongoose #indexing

#mongodb #мангуст #индексирование

Вопрос:

Мне нужно создать индекс для следующего запроса:

 await Activity.find({
   $and: [
      {
         lastUpdated: {
            $gte: new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000),
         },
      },
      {
         "followers._user": _user,
      },
      {
         global: true,
      }
   ]
})
.collation({
   locale: "en_US",
   numericOrdering: true,
})
.sort({
   lastUpdated: -1
})
.skip(
   length
)
.limit(
   10
)
 

В настоящее время у меня есть приведенный ниже индекс, но запрос его не использует.

 ActivitiesSchema.index(
  { "followers._user": 1, global: 1, lastUpdated: -1 },
  {
    collation: {
      locale: "en_US",
      numericOrdering: true,
    },
  }
);
 

Что я могу попытаться решить?

Комментарии:

1. Как вы узнаете, используется он или нет? Обычно я бы выполнил запрос в MongoShell, используя explain(), чтобы увидеть, как планировщик ожидает выполнения запроса. Вы проверили, что индекс был создан? Вообще говоря, создание индексов в вашем приложении — плохая практика, поскольку создание индекса может создать нагрузку на загруженную систему. Вместо того, чтобы приложение создавало индекс, рекомендуется создавать индекс в нерабочее время. При использовании MMS (Atlas, Ops Manager) вы можете применять индекс в скользящем режиме с небольшим воздействием на производственную систему.

2. @barrypicker Я поддерживаю каждое слово относительно управления индексами на уровне приложений, но сообщество Mongoose придерживается несколько иного мнения по этому вопросу mongoosejs.com/docs/guide.html#indexes . Они рекомендуют отключить автоматическое обновление индекса в производственных системах, поэтому было бы несправедливо называть это «плохой практикой» и вводить в заблуждение людей, которые только начали изучать этот довольно популярный ODM.

3. @barrypicker Атлас показывает мне, что он не использовался в течение X дней, вот откуда я знаю. По какой-то причине я не могу заставить explain() работать на меня, но я вижу объяснение на вкладке профиля в Atlas, которое показывает мне, что более 2 тыс. записей (все они) сканируются и возвращаются. Я слышу вас с созданием индексов, но это единственное бизнес-приложение, расположенное в одной области и оказывающее очень незначительное влияние на производственную систему, поскольку я делаю обновления в нерабочее время.

4. Вам не нужен индекс, если вся ваша коллекция содержит только 2 тыс. документов.

5. @AlexBlex Я знаю это для производства. Это числа из моей базы данных разработки.

Ответ №1:

Измените индекс на:

 { lastUpdated: -1, "followers._user": 1, global: 1 }
 

ПРИМЕЧАНИЕ: это может повлиять на другие запросы, которые полагаются на существующий индекс

https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/#sort-and-index-prefix читает:

Если ключи сортировки соответствуют ключам индекса или префиксу индекса, MongoDB может использовать индекс для сортировки результатов запроса. Префикс составного индекса — это подмножество, состоящее из одного или нескольких ключей в начале шаблона ключей индекса.

Поскольку вы сортируете по «lastUpdated», индекс должен начинаться с него.

ПРИМЕЧАНИЕ 2: с этим изменением Mongodb может использовать, но это не гарантируется. Существует много других факторов, таких как избирательность и мощность, например global: true, , подразумевает чрезвычайно низкую мощность, чтобы извлечь выгоду из индекса в этом поле. С другой стороны, если пользователь мало подписывается, а общая активность велика, может быть дешевле отфильтровать по индексу «followers._user» и выполнить сортировку в памяти. Планировщик запросов должен решить, какой индекс использовать.

Комментарии:

1. Это сделало это! Спасибо!