Зачем нужен дополнительный этап LIMIT с составным индексом в Mongo

Я использую Mongo 4.2 (застрял на этом) и имею коллекцию product_data с документами со следующей схемой:

_id:"2lgy_itmep53vy"
uIdHash:"2lgys2yxouhug5xj3ms45mluxw5hsweu"
userTS:1494055844000

Случай 1. При этом у меня есть следующие индексы для коллекции:

  1. _id:Обычный - Уникальный
  2. uIdHash: Хэшированный

я пытался выполнить

db.product_data.find( {"uIdHash":"2lgys2yxouhug5xj3ms45mluxw5hsweu"}).sort({"userTS":-1}).explain()

и это этапы в результате:

1

Конечно, я мог понять, что имело бы смысл иметь дополнительный составной индекс, чтобы избежать этапа сортировки в памяти mongo.

Случай 2: теперь я попытался добавить еще один индекс к уже существующим 3. {uIdHash:1, userTS:-1}: обычный и составной

Как я и ожидал, результат выполнения здесь удалось оптимизировать на этапе сортировки:

2



Пока все хорошо, теперь, когда я хочу создать разбиение на страницы поверх этого запроса. Мне нужно ограничить запрашиваемые данные. Следовательно, запрос далее переводится в

db.product_data.find( {"uIdHash":"2lgys2yxouhug5xj3ms45mluxw5hsweu"}).sort({"userTS":-1}).limit(10).explain()

Результат для каждого случая теперь выглядит следующим образом:

Результат ограничения случая 1: введите здесь описание изображения

Сортировка в памяти работает меньше (36 вместо 50) и возвращает ожидаемое количество документов. Достаточно справедливо, хорошая базовая оптимизация на этапе.

Результат ограничения случая 2: введите здесь описание изображения Удивительно, но с используемым индексом и запрошенными данными к обработке добавлен дополнительный этап Limit!

Сомнения теперь у меня следующие:

  1. Зачем нам дополнительный этап для LIMIT, когда у нас уже есть 10 документов, возвращенных из этапа FETCH?
  2. Каковы будут последствия этого дополнительного этапа? Учитывая, что мне нужна нумерация страниц, следует ли мне придерживаться индексов варианта 1 и не использовать последний составной индекс?

person Naman    schedule 25.01.2021    source источник


Ответы (2)


Стадия ограничения сообщает вам, что база данных ограничивает набор результатов. Это означает, что последующие этапы будут работать с меньшим объемом данных.

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

person D. SM    schedule 25.01.2021
comment
вопрос основан на том, почему база данных выполняет избыточную работу в пределе. обратите внимание на возвращаемые значения сканирования и этапа выборки, они уже предоставили только 10 документов, в то время как в общей сложности было 24 документа, которые могли совпасть. Просто чтобы возразить, он сообщает вам, что он сделал это, сообщая вам, что существует предельная стадия, которая должна быть поведением с одним хешированным индексом (случай 1), верно? (Я не верю, что он просто пытается донести до меня, что я позвонил в LIMIT.) - person Naman; 25.01.2021
comment
Предельный этап — это то, что создает 10 документов, поэтому он не является избыточным. С чем это будет лишним? - person D. SM; 25.01.2021
comment
Обратите внимание на значение nReturned на этапах FETCH и IXSCAN. Документы возвращены уже 10 изнутри. - person Naman; 26.01.2021
comment
Выборка и сканирование индекса вернутся ко всей коллекции. Это предельная стадия, которая останавливает их на 10 документах. - person D. SM; 26.01.2021
comment
Не совсем уверен, что понял предыдущий комментарий. Не могли бы вы объяснить возврат ко всей коллекции.? - person Naman; 26.01.2021
comment
Я разместил это до этого в сообществе, где этот ответ помог мне понять детали. Упоминание курсора и его релевантности оправдывает использование limit этапа. - person Naman; 03.02.2021

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

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

В неиндексной сортировке нет стадии дискретного ограничения, поскольку она сочетается с стадией сортировки.

person Joe    schedule 26.01.2021
comment
Должен ли я сделать из этого вывод, что ixscan и fetch сами по себе являются непрерывающими операциями, и они по-прежнему работали и возвращали 24 документа, просто добавление стадии ограничения заставляет отображать 10? - person Naman; 26.01.2021
comment
Нет, это одно из преимуществ использования индекса для выбора и сортировки: на обоих этапах можно раньше отказаться от проверки ключей и документов. - person Joe; 26.01.2021