нижняя линия/лин; др: Index b
может быть «пропущен», если a
и c
опрашиваются для равенства или неравенства, а не, например, для сортов на c
.
Это очень хороший вопрос. К сожалению, я не мог найти ничего, что авторитетно ответит на это более подробно. Я считаю, что выполнение таких запросов улучшилось за последние годы, поэтому я не стал бы доверять старым материалам по этой теме.
Все это является довольно сложным, поскольку она зависит от селективности по индексам и запрашивать ли вы за равенство, неравенство и/или сортировки, так explain()
твой единственным друг, но вот некоторые вещи, которые я нашел:
Caveat: Что происходит сейчас, это смесь экспериментальных результатов, рассуждений и угадываний.Возможно, я слишком сильно искажаю аналогию Кайла, и Возможно, я даже ошибаюсь (и не повезло, потому что мои результаты теста не совпадают с моими рассуждениями).
Понятно, что можно использовать индекс A, который, в зависимости от селективности A, безусловно, очень полезен. «Пропуск» B может быть сложным, или нет. Давайте держать это похоже на Kyle's cookbook example:
French
Beef
...
Chicken
Coq au Vin
Roasted Chicken
Lamb
...
...
Если теперь вы спросите меня, чтобы найти какой-то французское блюдо под названием «Шатобриан», я могу использовать индекс A
и, потому что я не знаю, ингредиент, будет сканировать все блюда в A
. С другой стороны, я знаю, что список блюд в каждой категории сортируется по индексу C
, поэтому мне нужно будет искать строки, начиная с, скажем, «Ча» в каждом списке ингредиентов. Если есть 50 ингредиентов, мне потребуется 50 поисковых запросов вместо одного, но это намного лучше, чем сканировать каждое французское блюдо!
В моих экспериментах, число было намного меньше, чем число различных значений в b
: она никогда не seemd превышать 2. Тем не менее, я проверил это только с одной коллекции, и это, вероятно, связано с селективность b
-index.
Если бы вы спросили меня, чтобы дать вам отсортированных в алфавитном порядке список всех французских блюд, хотя, я бы в неприятности. Теперь индекс на C
бесполезен, мне придется объединить сортировку всех этих индексных списков. Мне придется сканировать каждый элемент, чтобы сделать это.
Это отражено в моих тестах. Вот несколько упрощенных результатов. Первоначальная коллекция имеет datetime, ints и строки, но я хотел, чтобы все было просто, так что теперь это все ints.
По существу, существует только два класса запросов: те, где nscanned
< = 2 * limit
, и те, которые должны сканировать всю коллекцию (документы 120 тыс.). Индекс {a, b, c}
:
// fast (range query on c while skipping b)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }});
// slow (sorting)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1});
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1});
// fast (can sort on c if b included in the query)
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1});
// fast (older tutorials claim this is slow)
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }});
Ваш пробег будет меняться.
Спасибо, это, пожалуй, лучшая информация, которую мы можем получить, учитывая (отмеченную) отсутствие авторитетных ссылок. В моем конкретном случае B - столбец с низкой избирательностью, и я делаю запрос «начинается с» на C. Итак, полагаю, исходя из вашего ответа, мой индекс ABC почти так же хорош как индекс AC для запроса в AC? Я знаю, что пробег будет меняться, поэтому я могу просто пойти с индексами AC и ABC на время ... –
Я думаю, он будет почти таким же хорошим, как AC-index, если вы не сортируете на C, а ' Объяснение() 'может вам точно сказать. Следите за «nscanned», он не должен быть намного больше, чем 'n'. – mnemosyn