MongoDb агрегат с лимитом и без лимита - PullRequest
1 голос
/ 27 февраля 2020

В монго существует коллекция. В коллекции 40 миллионов записей

db.getCollection('feedposts').aggregate([

   {
        "$match": {
            "$or": [
                {
                  "isOfficial": true
                },
                {
                  "creator": ObjectId("537f267c984539401ff448d2"),
                   type: { $nin: ['challenge_answer', 'challenge_win']}

                }
            ],
        }
  },
  {
      $sort: {timeline: -1}
  }
])

Этот запрос никогда не заканчивается

Но если вы добавите ограничение перед сортировкой, а ограничение будет больше, чем общее количество записей заранее, например, 1 000 000 000 000 000 - запрос будет обработан мгновенно

db.getCollection('feedposts').aggregate([

   {
        "$match": {
            "$or": [
                {
                  "isOfficial": true
                },
                {
                  "creator": ObjectId("537f267c984539401ff448d2"),
                   type: { $nin: ['challenge_answer', 'challenge_win']}

                }
            ],
        }
  },
   {
      $limit: 10000000000000000
  },

  {
      $sort: {timeline: -1}
  }
])

Скажите, пожалуйста, почему это происходит? Какие проблемы могут возникнуть в будущем, если я оставлю это так?

1 Ответ

3 голосов
/ 27 февраля 2020

TLDR: Пн go использует неверный индекс для запроса

Почему это происходит?

Ну, в основном, каждый запрос Вы выполняете Mon go, имитируя быструю «конкуренцию» между соответствующими индексами, чтобы выбрать, какой из них использовать, первый индекс для извлечения 1001 документа «выигрывает».

Теперь обычно это ситуация выбора неправильной Индекс происходит с возрастающим или нисходящим полем и совпадает индекс, делающий этот индекс с извлечением конкуренции при определенных условиях. Это означает, что это очень рискованно, поскольку вы можете иметь стабильный код, который может внезапно стать огромным узким местом.

Что мы можем сделать?

У вас есть несколько вариантов:

  1. Используйте параметр hint и сделайте Mon go используйте составной индекс, который вы готовы для этого конвейера.
  2. Удалите мошеннический индекс, чтобы никогда больше этого не повториться (это мой рекомендуемый вариант).
  3. Продолжайте делать то, что вы делает. в основном, добавляя эту случайную $limit стадию, вы исключаете соревнование Mon go и гарантируете, что будет выбран правильный индекс.
...