#mongodb #indexing #aggregation-framework
#mongodb #индексирование #агрегация-фреймворк
Вопрос:
Использование mongo 3.2.
Пытался найти информацию, использует ли агрегация mongodb разреженные индексы.
- https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/
При размещении в начале конвейера операции $match используют подходящие индексы для сканирования только соответствующих документов в коллекции.
- 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"
},