Ще се опитам да обясня какво означава това с пример. Индексите, базирани на B-дърво, не са нещо специфично за mongodb. За разлика от това, това е доста често срещано понятие.
Така че, когато създавате индекс - вие показвате на базата данни по-лесен начин да намерите нещо. Но този индекс се съхранява някъде с указател, сочещ към местоположението на оригиналния документ. Тази информация е подредена и можете да я разглеждате като двоично дърво, което има наистина хубаво свойство:търсенето е намалено от O(n)
(линейно сканиране) към O(log(n))
. Което е много по-бързо, защото всеки път съкращаваме нашето пространство наполовина (потенциално можем да намалим времето от 10^6 на 20 търсения). Например имаме голяма колекция с поле {a : some int, b: 'some other things'}
и ако го индексираме с a, ще получим друга структура от данни, която е сортирана по a
. Изглежда така (с това нямам предвид, че е друга колекция, това е само за демонстрация):
{a : 1, pointer: to the field with a = 1}, // if a is the smallest number in the starting collection
...
{a : 999, pointer: to the field with a = 990} // assuming that 999 is the biggest field
Така че в момента търсим поле a =18. Вместо да преминаваме един по един през всички елементи, ние вземаме нещо по средата и ако е по-голямо от 18, тогава разделяме долната част наполовина и проверяваме елемента там . Продължаваме, докато намерим a =18. След това гледаме показалеца и знаейки го, извличаме оригиналното поле.
Ситуацията със съставния индекс е подобна (вместо да подреждаме по един елемент, ние подреждаме по много). Например имате колекция:
{ "item": 5, "location": 1, "stock": 3, 'a lot of other fields' } // was stored at position 5 on the disk
{ "item": 1, "location": 3, "stock": 1, 'a lot of other fields' } // position 1 on the disk
{ "item": 2, "location": 5, "stock": 7, 'a lot of other fields' } // position 3 on the disk
... huge amount of other data
{ "item": 1, "location": 1, "stock": 1, 'a lot of other fields' } // position 9 on the disk
{ "item": 1, "location": 1, "stock": 2, 'a lot of other fields' } // position 7 on the disk
и искате индекс { "item":1, "location":1, "stock":1 }. Справочната таблица ще изглежда така (още веднъж - това не е друга колекция, това е само за демонстрация):
{ "item": 1, "location": 1, "stock": 1, pointer = 9 }
{ "item": 1, "location": 1, "stock": 2, pointer = 7 }
{ "item": 1, "location": 3, "stock": 1, pointer = 1 }
{ "item": 2, "location": 5, "stock": 7, pointer = 3 }
.. huge amount of other data (but not necessarily here. If item would be one it would be somewhere next to items 1)
{ "item": 5, "location": 1, "stock": 3, pointer = 5 }
Вижте, че тук всичко е основно сортирано по елемент, след това по местоположение и след това по показалец. По същия начин, както при единичен индекс, не е необходимо да сканираме всичко. Ако имаме заявка, която търси item = 2, location = 5 and stock = 7
можем бързо да идентифицираме къде са документите с item = 2
са и след това по същия начин бързо идентифицирайте къде сред тези елементи елемент с location 5
и така нататък.
А сега една интересна част . Също така създадохме само един индекс (въпреки че това е съставен индекс, той все още е един индекс), можем да го използваме за бързо намиране на елемента
- само от
item
. Наистина всичко, което трябва да направим, е само първата стъпка. Така че няма смисъл да създавате друг индекс {location:1}, тъй като той вече е покрит от съставен индекс. - също така можем бързо да намерим само по
item and by location
(трябват ни само 2 стъпки).
Cool 1 индекс, но ни помага по три различни начина. Но изчакайте малко:какво ще стане, ако искаме да намерим по item and stock
. О, изглежда, че можем да ускорим и тази заявка. Можем в log(n) да намерим всички елементи с конкретен елемент и ... тук трябва да спрем - магията свърши. Трябва да преминем през всички тях. Но все пак доста добре.
Но може да ни помогне с други запитвания. Нека разгледаме заявка по location
което изглежда вече е поръчано. Но ако го погледнете - виждате, че това е бъркотия. Един в началото и после един в края. Това изобщо не може да ви помогне.
Надявам се това да изясни няколко неща:
- защо индексите са добри (намалете времето от O(n) до потенциално O(log(n))
- защо комбинираните индекси могат да помогнат с някои заявки, въпреки това не сме създали индекс за това конкретно поле и да помогнем с някои други заявки.
- кои индекси са обхванати от съставния индекс
- защо индексите могат да навредят (създава допълнителна структура от данни, която трябва да се поддържа)
И това трябва да каже друго валидно нещо:индексът не е сребърен куршум . Не можете да ускорите всичките си заявки, така че звучи глупаво да мислите, че чрез създаване на индекси на всички полета ВСИЧКО ще бъде супер бързо.