Mongodb продуктивність запитів на діапазонах

Якщо ви подорожували по території індексів MongoDB, ви можливо чули принцип: якщо ваші запити містять сортування, то добавте сортувати поле в кінець індексу який використовується в цих запитах. У багатьох випадках коли запити містять умови рівності як наприклад, принцип який вище дуже корисний.


Але що про нього можна сказати з наступним прикладом:

Цей зв'язок двох посад є не ефективною, хоча принцип дотримується. Тому що тут є пастка в яку вас може привести цей принцип. Нижче ми розглянемо причини возніконвенія цієї пастки і до кінця статті ви будете мати нове правило яке буде вам допомагати при індексуванні.

Давайте згадаємо основи з документації MongoDB:

Індекси заслуговують розгляду на початку проектування. Історичний, ефективність на рівні доступу до даних була перекладена на адміністраторів баз даних, це створювало шар оптимізації після проектування. З документо-оріентірованниім базами даних є можливість цього уникнути.

Індексовані запити працюють краще на кілька порядків, навіть на маленьких даних. У той час як без індексу запит може зайняти 10 секунд, той же запит може зайняти 0 мілісекунд з відповідним індексом.

Запити використовують індекси зліва направо. Індекс може бути використаний лише за умови що запит використовує всі поля в індексі без пропусків.

Якщо ваш запит буде містити сортування, то добавте сортувати поле в ваш індекс.

  • «Команди»
.explain () покаже який індекс використовується для даного запиту. ensureIndex () створює індекси. getIndexes () і .getIndexKeys () покажуть які індекси у вас є.

Тепер повернемося до нашого питання. З урахуванням основ індексації, для наступного запиту:

Ми повинні створити такий індекс:

Що якщо більшість запитів в умови використовують вибір діапазону замість порівняння? Як в цьому:

Тут ми використовували оператор $ in, але крім нього є ще такі як: $ gt, $ lt, і ін.

Якщо ви будете використовувати подібний запит, ви побачите що він не ефективний, при цьому ви пам'ятаєте основи - потрібно запустити .explain () і подивитися який індекс використовується і як.

В результаті виконання .explain () Ви побачите, що значить MongoDB виконує сортувальні операції, а це дорога операція тому MongoDB сортує документи в пам'яті. Тому Ви повинні уникати больших наборів даних тому це повільно і ресурсомісткість.

Не потрібно забувати, чому scanAndOrder повільний, чому MongoDB сортує результат хоча у нас вже є індекс з сортуванням? Відповідь проста: у нас немає відповідного індексу.

Чому? Причина проста, справа в структурі індексу який ми створили. Для прикладу вище, документи мають і документи мають відсортовані в індіксе по, але вони сортуються незалежно один від одного. Вони не відсортовані разом! Розглянемо діаграму нижче:


На лівій схемі показаний порядок обходу документів за індексом який ми створили. Після того як всі документи будуть знайдені, їх потрібно буде впорядкувати.

На правій схемі альтернативний індекс <“carsOwned”: 1, “country”: 1>. В цьому випадку знайдені документи будуть вже в відсортованому вигляді.

Цей тонкий момент ефективності привів до наступних правил при індексації:

Порядок полів повинен бути:

1. Спочатку поля які відбираються з точних значень.

2. Далі поля за якими буде йти сортування.

3. І в кінці поля для діапазонного фільтра.

Чи є компромміс? Так. Запит буде відвідувати кілька вузлів індексу, що технічний необхідно, тому що обхід сортованого частини відбуватиметься до фільтрування. Таким чином нове правило як чиста прибл для багатьох запитів, але не забувайте що складність ваших даних може призводити до різних результатів.