Чому напрямок індексу має значення в MongoDB?


114

Щоб процитувати документи :

Під час створення індексу число, пов’язане з ключем, вказує напрям індексу, тому він завжди повинен бути 1 (зростаючий) або -1 (низхідний). Напрямок не має значення для індивідуальних ключових індексів або для випадкового доступу, але важливий, якщо ви робите запити сортування чи діапазону на складених індексах.

Однак я не бачу причин, чому напрям індексу має значення для складних індексів. Може хтось, будь ласка, надати додаткове пояснення (чи приклад)?

Відповіді:


112

MongoDB певним чином з'єднує складений ключ і використовує його як ключ у BTree.

При знаходженні окремих елементів - Порядок вузлів на дереві не має значення.

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

З одним індексом поля - Порядок не має значення. Якщо вони розташовуються близько у порядку зростання, вони також будуть близько в порядку спадання.

Коли у вас є складний ключ - Порядок починає мати значення.

Наприклад, якщо ключ A висхідний B за зростанням, індекс може виглядати приблизно так:

Ряд AB
1 1 1
2 2 6
3 2 7 
4 3 4
5 3 5
6 3 6
7 5 1

Для запиту на висхідний B, що спадає B, потрібно буде стрибати навколо індексу, щоб повернути рядки, і буде повільніше. Наприклад, він поверне рядок1, 3, 2, 6, 5, 4, 7

Діапазон запитів у тому ж порядку, що й індекс, просто поверне рядки послідовно у правильному порядку.

Пошук запису в BTree займає час O (Log (n)). Пошук за порядком діапазону записів - це лише OLog (n) + k, де k - кількість записів, які потрібно повернути.

Якщо записи вийшли з ладу, вартість може бути такою ж, як OLog (n) * k


1
Отриманий рядок, мабуть, має бути 1, 3, 2, 6, 5, 4, 7?
johndodo

Я все ще не бачу причини, щоб це було повільніше. Тільки алгоритм повинен бути різним (для кожної групи значень у А він повинен переходити до кінця групи та обробляти його у зворотному порядку), але оскільки індекси MongoDB знаходяться в пам'яті, які не повинні мати помітного впливу на швидкість. Також RDBMS нічого не знає про напрямок з індексами і ситуація там досить схожа на afaik?
johndodo

8
Причина, по якій це хіт продуктивності, полягає в тому, що це не просто послідовний список пам'яті, як спрощений приклад. Це насправді зважене дерево. Стрибки з ладу включатимуть знову обхід дерева. RDMS остаточно мають порядок індексування.
Джаред Келлс

1
Збирати вузли з BTree так само просто, як рухатися по кожному листу, поки ви не закінчите, а потім піднімаєтесь на рівень і вниз по наступній гілці. Це O (n) Не в порядку, це набагато більш інтенсивно процесора.
Джаред Келлс

Дякуємо за подальше уточнення. Я перевірив документи на індекси MySQL - дійсно можна вказати напрямок індексу, але налаштування ігнорується.
johndodo

45

Проста відповідь , який ви шукаєте, що напрямок має значення тільки тоді , коли розбирають на двох або більше полів .

Якщо ви сортуєте {a : 1, b : -1}:

Індекс {a : 1, b : 1}буде повільніше, ніж індекс{a : 1, b : -1}


1
@MarkPieszak, тому що весь сорт повинен був би бути зроблений в пам'яті, зробивши індекс непотрібним
Sammaye

@Sammaye Я думаю, що це правильна ідея, хоча я не впевнений, що це весь сорт. Я мав би подивитися на реалізацію , щоб знати , як це дійсно працює, але я думаю , що результати можуть бути відсторонився відсортовані по в поодинці, а потім додаткові б - то потрібно було б зробити в пам'яті.
Заїд Масуд

1
хм, дивно востаннє, коли я перевіряв код, він відкинув часткові сорти через те, як сортування було, але мені, можливо, воно змінилося
Sammaye

Що робити, якщо я буду сортувати {a: -1, b: -1}, чи повинен я мати {a: -1, b: -1}індекс або буде {a: 1, b: 1}достатньо.
Хуссей

@Hussain у вашому прикладі {a: 1, b: 1}індексу має бути достатнім, оскільки інвертування індексу повністю нормальне. наприклад, Index on {a: 1}може бути використаний для сортування на{a: -1}
Zaid Masud

12

Чому індекси

Зрозумійте два ключові моменти.

  1. Хоча індекс кращий, ніж індекс, правильний індекс набагато кращий за будь-який інший.
  2. MongoDB використовуватиме лише один індекс на запит, створюючи складні індекси з належним упорядкуванням поля, що ви, ймовірно, хочете використовувати.

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

Як індекси

Визначення групи полів, яку слід індексувати разом, - це розуміння запитів, які ви виконуєте. Порядок полів, які використовуються для створення вашого індексу, є критичним. Хороша новина полягає в тому, що, якщо ви помилилися з замовленням, індекс взагалі не буде використовуватися, тому його легко помітити з поясненням.

Чому сортування

Ваші запити можуть потребувати сортування. Але сортування може бути дорогою операцією, тому важливо ставитися до полів, за якими ви сортуєте так само, як до поля, яке ви запитуєте. Так буде швидше, якщо він буде мати індекс. Однак є одна важлива відмінність: поле, яке ви сортуєте, повинно бути останнє поле у ​​вашому індексі. Єдиним винятком із цього правила є те, що поле також є частиною вашого запиту, тоді правило must-be-last не застосовується.

Як сортування

Ви можете вказати сортування на всіх клавішах індексу або на підмножині; однак ключі сортування повинні бути вказані в тому ж порядку, що і в індексі. Наприклад, шаблон індексного ключа {a: 1, b: 1} може підтримувати сортування на {a: 1, b: 1}, але не на {b: 1, a: 1}.

Сортування повинен визначати той самий напрямок сортування (тобто висхідний / низхідний) для всіх його ключів, як шаблон індексного ключа або задавати зворотний напрямок сортування для всіх його ключів, як шаблон індексного ключа. Наприклад, шаблон індексного ключа {a: 1, b: 1} може підтримувати сортування на {a: 1, b: 1} та {a: -1, b: -1}, але не на {a: -1 , b: 1}.

Припустимо, є ці показники:

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }

Example                                                    Index Used
db.data.find().sort( { a: 1 } )                            { a: 1 }
db.data.find().sort( { a: -1 } )                           { a: 1 }
db.data.find().sort( { a: 1, b: 1 } )                      { a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } )                    { a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } )                { a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )   { a: 1, b: 1 }

Я розумію, що це приклад, але якщо є індекс, { a: 1, b: 1, c: 1 }чи справді вам потрібні індекси { a: 1}та { a: 1, b: 1}чи індекс { a: 1, b: 1, c: 1 }охоплює всі випадки? Якщо в запитах завжди використовується один і той же сорт: 1 немає сортування в запиті з -1
Лукас Лієсіс

1
Якщо є багато запитів, які працюють лише над властивістю 'a', то швидше шукати за допомогою індексу з властивістю 'a' для двигуна бази даних, ніж пошук за індексом з 3 властивостями 'a', 'b', 'c'. Тому що розмір індексу збільшиться, а кількість також зросте. колишній Якщо в книзі є 20 глав. Тож швидше перейти до розділу 3, а потім на певну сторінку. @LukasLiesis
Muluk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.