MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDb:как да създадете правилния (съставен) индекс за данни с много полета за търсене

Ще се опитам да обясня какво означава това с пример. Индексите, базирани на 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))
  • защо комбинираните индекси могат да помогнат с някои заявки, въпреки това не сме създали индекс за това конкретно поле и да помогнем с някои други заявки.
  • кои индекси са обхванати от съставния индекс
  • защо индексите могат да навредят (създава допълнителна структура от данни, която трябва да се поддържа)

И това трябва да каже друго валидно нещо:индексът не е сребърен куршум . Не можете да ускорите всичките си заявки, така че звучи глупаво да мислите, че чрез създаване на индекси на всички полета ВСИЧКО ще бъде супер бързо.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Опресняване на браузъра чрез събитие OnBeforeUnload

  2. WAMP MongoDB - PHP разширение

  3. Вграден документ срещу препратка в модела на дизайн на мангуста?

  4. Тестване за интеграция на Spring Boot с вграден MongoDB

  5. Mongoose позволява ли едновременно множество заявки за база данни?