MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDb:come creare il giusto indice (composito) per i dati con molti campi ricercabili

Cercherò di spiegare cosa significa questo con un esempio. Gli indici basati su B-tree non sono qualcosa di specifico di mongodb. Al contrario è un concetto piuttosto comune.

Quindi, quando crei un indice, mostri al database un modo più semplice per trovare qualcosa. Ma questo indice è memorizzato da qualche parte con un puntatore che punta a una posizione del documento originale. Questa informazione è ordinata e potresti vederla come un albero binario che ha una proprietà davvero interessante:la ricerca è ridotta da O(n) (scansione lineare) su O(log(n)) . Il che è molto molto più veloce perché ogni volta dimezziamo il nostro spazio (potenzialmente possiamo ridurre il tempo da 10^6 a 20 ricerche). Ad esempio abbiamo una grande collezione con campo {a : some int, b: 'some other things'} e se lo indicizziamo per a, finiamo con un'altra struttura di dati che è ordinata per a . Sembra così (con questo non intendo che sia un'altra collezione, questo è solo a scopo dimostrativo):

{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

Quindi in questo momento stiamo cercando un campo a =18. Invece di passare uno per uno attraverso tutti gli elementi prendiamo qualcosa nel mezzo e se è più grande di 18, allora dividiamo la parte inferiore a metà e controlliamo l'elemento lì . Continuiamo finché non troveremo a =18. Quindi osserviamo il puntatore e sapendolo estraiamo il campo originale.

La situazione con l'indice composto è simile (invece di ordinare per un elemento, ordiniamo per molti). Ad esempio hai una collezione:

{ "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

e vuoi un indice { "item":1, "location":1, "stock":1 }. La tabella di ricerca sarebbe simile a questa (ancora una volta - questa non è un'altra raccolta, è solo a scopo dimostrativo):

{ "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 }

Vedi che qui tutto è fondamentalmente ordinato per elemento, quindi per posizione e quindi per puntatore. Allo stesso modo di un singolo indice, non abbiamo bisogno di scansionare tutto. Se abbiamo una query che cerca item = 2, location = 5 and stock = 7 possiamo identificare rapidamente dove i documenti con item = 2 sono e quindi allo stesso modo identificare rapidamente dove tra questi elementi l'articolo con location 5 e così via.

E in questo momento una parte interessante . Inoltre abbiamo creato un solo indice (sebbene questo sia un indice composto, è comunque un indice) possiamo usarlo per trovare rapidamente l'elemento

  • solo dall'item . Davvero tutto ciò che dobbiamo fare è solo il primo passo. Quindi non ha senso creare un altro indice {location :1} perché è già coperto da un indice composto.
  • inoltre possiamo trovare rapidamente solo per item and by location (abbiamo bisogno solo di 2 passaggi).

Cool 1 index ma ci aiuta in tre modi diversi. Ma aspetta un minuto:e se volessimo trovare per item and stock . Oh, sembra che possiamo velocizzare anche questa query. Possiamo in log(n) trovare tutti gli elementi con un oggetto specifico e ... qui dobbiamo fermarci:la magia è finita. Abbiamo bisogno di scorrere tutti loro. Ma comunque abbastanza buono.

Ma possa aiutarci con altre domande. Diamo un'occhiata a una query per location che sembra già ordinato. Ma se lo guardi, vedi che questo è un pasticcio. Uno all'inizio e poi uno alla fine. Non può aiutarti affatto.

Spero che questo chiarisca alcune cose:

  • perché gli indici sono buoni (ridurre il tempo da O(n) a potenzialmente O(log(n))
  • perché gli indici composti possono essere utili con alcune query, tuttavia non abbiamo creato un indice su quel campo particolare e aiutano con altre query.
  • quali indici sono coperti dall'indice composto
  • perché gli indici possono danneggiare (crea una struttura dati aggiuntiva che dovrebbe essere mantenuta)

E questo dovrebbe dire un'altra cosa valida:l'indice è non un proiettile d'argento . Non puoi velocizzare tutte le tue query, quindi sembra sciocco pensare che creando indici su tutti i campi TUTTO sarebbe super veloce.