Использует ли агрегация mongodb разреженные индексы

#mongodb #indexing #aggregation-framework

#mongodb #индексирование #агрегация-фреймворк

Вопрос:

Использование mongo 3.2.

Пытался найти информацию, использует ли агрегация mongodb разреженные индексы.

  1. https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/

    При размещении в начале конвейера операции $match используют подходящие индексы для сканирования только соответствующих документов в коллекции.

  2. https://docs.mongodb.com/manual/core/index-sparse/

    Даже если сортировка выполняется по индексированному полю, MongoDB не выберет разреженный индекс для выполнения запроса, чтобы вернуть полные результаты : … Чтобы использовать разреженный индекс, явно укажите индекс с помощью hint()

Итак, вопрос в том, если у меня разреженный индекс, будет ли конвейер агрегации mongo с совпадением в индексированном поле использовать его или нет?

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

1. Привет, платформа агрегации имеет возможность добавить explain опцию — если у вас уже есть образец данных и индекса, просто добавьте такую explain опцию: db.orders.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, { $sort: { total: -1 } } ], { explain: true } ) Он сообщит вам, использует ли он его.

2. @cohenjo explain в aggregation не предоставляет executionStats, поэтому не может проверить, является ли агрегация с использованием разреженного индекса или нет.

Ответ №1:

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

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

Другой случай, когда разреженный индекс нельзя использовать, — это когда вы фильтруете по полю, но с запросом типа { x: { $exists: false } } where разреженный индекс не будет содержать совпадающих результатов (потому что он специально исключает их).

В вашем случае, как вы говорите $match , выполняется фильтрация по полю с разреженным индексом, разреженный индекс можно использовать, если индекс будет содержать полные результаты, например, вы проверяете равенство или используете оператор сравнения типа $gte etc, но не оператор типа $ne or { $exists: false } .

Вы можете подтвердить с помощью команды explain, даже без executionStats .

Из запроса агрегации тестов с {$match:{a:4}} неиндексированным полем и a выполняется проверка коллекции:

 "winningPlan" : {
    "stage" : "COLLSCAN",
    "filter" : {
        "a" : {
            "$eq" : 4
        }
    },
    "direction" : "forward"
},
  

Из запроса агрегации тестов с {$match:{b:4}} полем b с разреженным индексом используется разреженный индекс:

 "winningPlan" : {
  "stage" : "FETCH",
  "inputStage" : {
      "stage" : "IXSCAN",
      "keyPattern" : {
          "b" : 1
      },
      "indexName" : "b_1",
      "isMultiKey" : false,
      "isUnique" : false,
      "isSparse" : true,
      "isPartial" : false,
      "indexVersion" : 1,
      "direction" : "forward",
      "indexBounds" : {
          "b" : [
              "[4.0, 4.0]"
          ]
      }
  }
},
  

Для запроса агрегации тестов с {$match:{b:{$exists:false}} полем с разреженным индексом b (это вернет неполные результаты с включенным разреженным индексом b ) выполняется сканирование коллекции:

 "winningPlan" : {
    "stage" : "COLLSCAN",
    "filter" : {
        "$not" : {
            "b" : {
                "$exists" : true
            }
        }
    },
    "direction" : "forward"
},