Чтобы устранить неполадки с медленными запросами, используйте Query Explain, чтобы получить план выполнения запроса и профиль выполнения во время выполнения. В следующем разделе описаны действия, которые можно предпринять для оптимизации производительности запросов в зависимости от профиля выполнения.
Ограничение количества результатов
Чтобы узнать, возвращает ли запрос много документов, используйте поле возвращенных записей в дереве выполнения. Рекомендуем ограничить количество возвращаемых документов с помощью оператора $limit. Это позволяет уменьшить размер сериализованных байтов результатов, возвращаемых клиентам по сети. Если узлу Limit
предшествует узел MajorSort, механизм запросов может объединить Limit
ихMajorSort и заменить полную материализацию в памяти и
сортировку на сортировку TopN, снизив требования к памяти для запроса.
Ограничение размера результирующего документа
Чтобы не получать ненужные поля, ограничьте размер возвращаемого документа с помощью предложения $project. Это помогает снизить затраты на вычисления и память при обработке промежуточных результатов и сериализованный размер байтов результатов при возврате клиентам по сети. Если все поля, на которые ссылается запрос, охвачены обычным индексом (не мультиключевым), это также позволяет полностью охватить запрос сканированием индекса, избегая необходимости извлекать документы из основного хранилища.
Использование индексов
Чтобы настроить и оптимизировать индексы, следуйте инструкциям ниже.
Определите, использует ли запрос индекс.
Чтобы определить, использует ли запрос индекс, проверьте конечные узлы в дереве выполнения. Если конечный узел дерева выполнения – это узел TableScan, значит, запрос не использует индекс и сканирует документы из основного хранилища. Если используется индекс, в конечном узле дерева выполнения будут показаны идентификатор и поля индекса.
Определите, можно ли оптимизировать используемый индекс.
Индекс полезен для запроса, если он может уменьшить количество документов, которые механизм запросов должен получить из основного хранилища, или если порядок его полей может обеспечить требование сортировки запроса.
Если индекс используется для запроса, но механизм запросов по-прежнему извлекает и отбрасывает много документов, что определяется узлом Scan, который возвращает много записей, за которым следует узел Filter, который возвращает мало записей, это признак того, что предикат запроса, удовлетворяемый с помощью индекса, не является селективным. Чтобы создать более подходящий индекс, ознакомьтесь с разделом Создание индексов.
Если для запроса используется индекс, не являющийся мультиключевым, но механизм запросов по-прежнему выполняет переупорядочение набора результатов в памяти, на что указывает узел MajorSort в дереве выполнения запроса, это означает, что используемый индекс не может быть использован для выполнения требования сортировки запроса. Чтобы создать более подходящий индекс, ознакомьтесь со следующим разделом.
Оптимизация запросов $lookup
Вы можете оптимизировать запросы $lookup, добавив индексы в коллекцию from. Это позволит эффективно находить нужные документы, не сканируя всю коллекцию.
$lookup с localField и foreignField
Если вы используете параметры localField и foreignField на этапе $lookup, создайте индекс для foreignField в коллекции from.
$lookup с вложенными конвейерами
Если вы используете параметр pipeline на этапе $lookup с этапами $match, создайте индекс для полей, задействованных во внешней коллекции, чтобы избежать полного сканирования коллекции:
- Для этапов
$matchс семантикой фильтра (например,{$match: {a: true}}) создайте индекс для полей, задействованных во внешней коллекции (a). - Для этапов
$matchс семантикой агрегирования, которая сравнивает поле с постоянным значением (например,{$match: {$expr: {$gt: [a, 10]}}}) или со сравнениями на равенство (eqилиin) между полями и переменными, определенными вlet(например,{$match: {$expr: {$eq: [a, "$$a"]}}}), создайте индекс для полей, задействованных во внешней коллекции. Обратите внимание, что мультиключевой индекс не будет использоваться при планировании.
Создание индексов
Следуйте инструкциям в документации по управлению индексами, чтобы создать индексы. Чтобы запрос мог использовать индексы, создайте обычные (не мультиключевые) индексы с полями в следующем порядке:
- Все поля, которые будут использоваться в операторах равенства. Чтобы повысить вероятность повторного использования в запросах, упорядочивайте поля в порядке убывания их встречаемости в операторах равенства в запросах.
- Все поля, по которым будет выполняться сортировка (в том же порядке).
- Поля, которые будут использоваться в операторах диапазона или неравенства в порядке убывания избирательности ограничений запроса.
- Поля, которые будут возвращены в составе запроса в индексе. Включение таких полей в индекс позволяет ему охватить запрос и избежать необходимости извлекать документ из основного хранилища.
Для запросов, включающих фильтрацию и сортировку полей массива, рекомендуется создавать мультиключевые индексы.
Использовать подсказку для запроса
Если вы создали более подходящий индекс для запроса, но поисковая система его не использует, вы можете переопределить предпочтения поисковой системы, используя подсказку к запросу.
Дополнительную информацию о выходных данных запроса, выполненного с помощью Query Explain, можно найти в справочнике по выполнению запросов.