Из раздела руководства MongoDB по составные индексы :
db.products.createIndex ({"item": 1, "stock": 1})
Порядок полей, перечисленных в составном индексе, важен. Индекс будет содержать ссылки на документы, отсортированные сначала по значениям поля элемента и, в пределах каждого значения поля элемента, отсортированные по значениям поля запаса.
Учитывая вышеизложенное, мы можем видеть, что a_1_b_1
будет сначала сегментироваться на a
, а затем на b
, тогда как b_1_a_1
будет сначала сегментироваться на b
, а затем на a
.
Теперь давайте рассмотрим ваш запрос: {a: x, b: { $in: [....] } }
Обратите внимание, что этот запрос соответствует определенному значению a
и диапазону возможных значений b
. В индексе a_1_b_1
сканирование индекса будет ограничено только соответствующим блоком a
, и все значения b
будут искать в пределах; однако, если вы используете индекс b_1_a_1
, то сканирование индекса должно «перепрыгнуть» между различными блоками b
и найти в каждом из них соответствующее значение a
.
Как правило, гораздо более эффективный доступ к данным, которые «близки» друг к другу, поэтому вам нужно выбрать индекс, в котором ваши совпадающие документы с большей вероятностью будут расположены близко. В этом случае все ваши документы в одном и том же блоке a
, вероятно, будут гораздо лучшим выбором, так как должно быть меньше «скачков», поэтому вы должны использовать индекс a_1_b_1
.
Однако это сильно упрощено. Фактическое влияние на производительность может быть незначительным, особенно в случаях, когда диапазон возможных значений a
и b
довольно низок.
Также необходимо учесть дополнительные префиксы запросов. Если вы оказались в ситуации, когда вы иногда выполняете запросы только со значением a
, вам следует выбрать индекс a_1_b_1
. Аналогично, если вы иногда выполняете запросы только со значением b
, то вам, вероятно, следует выбрать b_1_a_1
.
Это потому, что если ваш запрос не полностью совпадает с индексом, но совпадает с префиксом этого индекса, индекс все равно будет применяться. Таким образом, в индексе a_1_b_1
вы можете выполнять эффективные запросы на {a: x, b: {$in: [....]}}
, а также {a: x}
, но вы не можете выполнить эффективный запрос на {b: {$in: [....]}}
.
Наконец, часто можно воспользоваться преимуществом пересечения индексов , чтобы иметь два отдельных индекса a_1
и b_1
, что дает вам среднюю точку между производительностью и гибкостью.
Имея в виду все вышесказанное, я бы не советовал слишком сильно относиться к производительности индекса, пока размер ваших данных не начнет это делать. В конце концов, вы можете удалить старые индексы и построить новые по мере необходимости. Используйте то, что работает на данный момент, следите за производительностью с течением времени и переоценивайте, когда кажется, что вы можете перерасти то, что используете в данный момент.