Perché la direzione dell'indice è importante in MongoDB?


114

Per citare i documenti :

Quando si crea un indice, il numero associato a una chiave specifica la direzione dell'indice, quindi dovrebbe essere sempre 1 (crescente) o -1 (decrescente). La direzione non è importante per gli indici a chiave singola o per il recupero ad accesso casuale, ma è importante se si eseguono query di ordinamento o intervallo su indici composti.

Tuttavia, non vedo alcun motivo per cui la direzione dell'indice dovrebbe avere importanza negli indici composti. Qualcuno può fornire un'ulteriore spiegazione (o un esempio)?

Risposte:


112

MongoDB concatena in qualche modo la chiave composta e la utilizza come chiave in un BTree.

Quando si trovano elementi singoli : l'ordine dei nodi nell'albero è irrilevante.

Se stai restituendo un intervallo di nodi : gli elementi vicini tra loro si troveranno lungo gli stessi rami dell'albero. Più i nodi sono vicini all'intervallo, più velocemente possono essere recuperati.

Con un singolo indice di campo : l'ordine non avrà importanza. Se sono ravvicinati in ordine crescente, saranno anche vicini in ordine decrescente.

Quando hai una chiave composta - L'ordine inizia a essere importante.

Ad esempio, se la chiave è A crescente B crescente, l'indice potrebbe essere simile a questo:

Riga AB
1 1 1
2 2 6
3 2 7 
4 3 4
5 3 5
6 3 6
7 5 1

Una query per A crescente B decrescente dovrà saltare intorno all'indice fuori ordine per restituire le righe e sarà più lenta. Ad esempio restituirà Row1, 3, 2, 6, 5, 4, 7

Una query con intervallo nello stesso ordine dell'indice restituirà semplicemente le righe in sequenza nell'ordine corretto.

Trovare un record in un BTree richiede tempo O (Log (n)). Trovare un intervallo di record in ordine è solo OLog (n) + k dove k è il numero di record da restituire.

Se i record sono fuori servizio, il costo potrebbe essere pari a OLog (n) * k


1
La riga risultante dovrebbe probabilmente essere 1, 3, 2, 6, 5, 4, 7?
johndodo

Non vedo ancora alcun motivo per essere più lento. Solo l'algoritmo dovrebbe essere diverso (per ogni gruppo di valori in A dovrebbe saltare alla fine del gruppo ed elaborarlo in ordine inverso), ma poiché gli indici MongoDB sono in memoria, ciò non dovrebbe avere alcun effetto evidente sulla velocità. Inoltre, RDBMS non sa nulla della direzione con gli indici e la situazione è abbastanza simile afaik?
johndodo

8
Il motivo per cui è un successo in termini di prestazioni è perché non è solo un elenco sequenziale in memoria come l'esempio semplificato. In realtà è un albero ponderato. Saltare fuori ordine comporterà nuovamente l'attraversamento dell'albero. Gli RDMS hanno definitivamente ordine agli indici.
Jared Kells,

1
Recuperare i nodi da un BTree in ordine è semplice come spostarsi lungo ciascuna foglia fino a quando non si esaurisce, quindi salire di un livello e scendere il ramo successivo. È O (n) Fuori servizio è molto più impegnativo per la CPU.
Jared Kells,

Grazie per ulteriori chiarimenti. Ho controllato i documenti per gli indici MySQL : è davvero possibile specificare la direzione dell'indice, ma l'impostazione viene ignorata.
johndodo

45

La semplice risposta che stai cercando è che la direzione è importante solo quando esegui l'ordinamento su due o più campi .

Se stai ordinando su {a : 1, b : -1}:

L'indice {a : 1, b : 1}sarà più lento dell'indice{a : 1, b : -1}


1
@MarkPieszak perché l'intero ordinamento dovrebbe essere fatto in memoria rendendo l'indice inutile
Sammaye

@Sammaye Credo che sia l'idea giusta, anche se non sono sicuro che sia l' intera specie. Dovrei guardare l'implementazione per sapere come funziona davvero, ma penso che i risultati potrebbero essere ritirati ordinati da un solo, e quindi l' ordinamento b aggiuntivo dovrebbe essere fatto in memoria.
Zaid Masud

1
hmm, strano l'ultima volta che ho controllato il codice ha perso ordinamenti parziali a causa di come era l'ordinamento ma meh, forse è cambiato
Sammaye,

E se sto ordinando {a: -1, b: -1}, dovrei avere {a: -1, b: -1}index o sarà {a: 1, b: 1}sufficiente.
Hussain

@ Hussain nel tuo esempio l' {a: 1, b: 1}indice dovrebbe essere sufficiente poiché invertire completamente un indice va bene. ad esempio, Indice su {a: 1}può essere utilizzato per un ordinamento su{a: -1}
Zaid Masud

12

Perché gli indici

Comprendi due punti chiave.

  1. Sebbene un indice sia migliore di nessun indice, l'indice corretto è molto migliore di entrambi.
  2. MongoDB utilizzerà solo un indice per query, creando indici composti con il corretto ordinamento dei campi che probabilmente si desidera utilizzare.

Gli indici non sono gratuiti. Prendono memoria e impongono una riduzione delle prestazioni durante gli inserimenti, gli aggiornamenti e le eliminazioni. Normalmente il calo delle prestazioni è trascurabile (soprattutto se paragonato all'aumento delle prestazioni di lettura), ma ciò non significa che non possiamo essere intelligenti nel creare i nostri indici.

Come indici

Identificare il gruppo di campi da indicizzare insieme significa comprendere le query che stai eseguendo. L'ordine dei campi utilizzati per creare il tuo indice è fondamentale. La buona notizia è che, se sbagli l'ordine, l'indice non verrà utilizzato affatto, quindi sarà facile individuarlo spiegando.

Perché ordinare

Le tue query potrebbero richiedere l'ordinamento. Ma l'ordinamento può essere un'operazione costosa, quindi è importante trattare i campi su cui stai ordinando proprio come un campo su cui stai interrogando. Quindi sarà più veloce se ha index. Tuttavia, c'è una differenza importante, il campo che stai ordinando deve essere l'ultimo campo del tuo indice. L'unica eccezione a questa regola è che se anche il campo fa parte della query, la regola deve essere l'ultima non si applica.

Come ordinare

È possibile specificare un ordinamento su tutte le chiavi dell'indice o su un sottoinsieme; tuttavia, le chiavi di ordinamento devono essere elencate nello stesso ordine in cui appaiono nell'indice. Ad esempio, un modello di chiave di indice {a: 1, b: 1} può supportare un ordinamento su {a: 1, b: 1} ma non su {b: 1, a: 1}.

L'ordinamento deve specificare la stessa direzione di ordinamento (cioè ascendente / discendente) per tutte le sue chiavi come modello di chiave di indice o specificare la direzione di ordinamento inversa per tutte le sue chiavi come modello di chiave di indice. Ad esempio, un pattern di chiave di indice {a: 1, b: 1} può supportare un ordinamento su {a: 1, b: 1} e {a: -1, b: -1} ma non su {a: -1 , b: 1}.

Supponiamo che ci siano questi indici:

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

Capisco che sia un esempio, ma se c'è un indice { a: 1, b: 1, c: 1 }, hai davvero bisogno di indici { a: 1}e / { a: 1, b: 1}o indice { a: 1, b: 1, c: 1 }copre tutti i casi? Se le query utilizzano sempre lo stesso ordinamento: 1 nessun ordinamento nella query con -1
Lukas Liesis

1
Se ci sono molte query che funzionano solo sulla proprietà "a", è più veloce cercare con indice con proprietà "a" per il motore di database, piuttosto che cercare per indice con 3 proprietà "a", "b", "c". Perché la dimensione dell'indice aumenterà e anche il conteggio aumenterà. ex. Se ci sono 20 capitoli nel libro. Quindi è più veloce andare al capitolo 3 e poi alla pagina specifica. @LukasLiesis
Somnath Muluk
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.