Puoi pensare all'indice a campo singolo MongoDB come a un array, con puntatori alle posizioni dei documenti. Ad esempio, se hai una collezione con (nota che la sequenza è deliberatamente fuori ordine):
[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}
Indice a campo singolo
Ora se lo fai:
db.collection.createIndex({a:1})
L'indice è approssimativamente simile a:
[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1
Nota tre cose importanti:
- È ordinato per
a
ascendente - Ogni ingresso punta al luogo in cui risiedono i documenti pertinenti
- L'indice registra solo i valori di
a
campo. Ilb
il campo non esiste affatto nell'indice
Quindi, se fai una query come:
db.collection.find().sort({a:1})
Tutto quello che deve fare è percorrere l'indice dall'alto verso il basso, prelevare ed emettere il documento indicato dalle voci. Nota che puoi anche percorrere l'indice dal basso, ad esempio:
db.collection.find().sort({a:-1})
e l'unica differenza è che percorri l'indice al contrario.
Perché b
non è affatto nell'indice, non puoi usare l'indice quando esegui query su b
.
Indice composto
In un indice composto es.:
db.collection.createIndex({a:1, b:1})
Significa che vuoi ordinare per a
prima, quindi ordina per b
. L'indice sarebbe simile a:
[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1
Nota che:
- L'indice è ordinato da
a
- All'interno di ogni
a
hai unb
ordinato - Hai 5 voci di indice rispetto alle sole tre del precedente esempio a campo singolo
Usando questo indice, puoi eseguire una query come:
db.collection.find({a:2}).sort({b:1})
Può facilmente trovare dove a:2
quindi sposta l'indice in avanti. Dato quell'indice, non puoi farlo :
db.collection.find().sort({b:1})
db.collection.find({b:1})
In entrambe le query non puoi trovare facilmente b
poiché è distribuito in tutto l'indice (cioè non in voci contigue). Comunque tu puoi fare:
db.collection.find({a:2}).sort({b:-1})
poiché puoi essenzialmente trovare dove si trova a:2
sono e percorri il b
voci indietro.
Modifica :chiarimento della domanda di @marcospgp nel commento:
La possibilità di utilizzare l'indice {a:1, b:1}
per soddisfare find({a:2}).sort({b:-1})
in realtà ha senso se lo vedi da un punto di vista della tabella ordinata. Ad esempio, l'indice {a:1, b:1}
può essere pensato come:
a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
trova({a:2}).sort({b:1})
L'indice {a:1, b:1}
significa sort by a, then within each a, sort the b values
. Se poi esegui un find({a:2}).sort({b:1})
, l'indice sa dove si trovano tutti i a=2
sono. All'interno di questo blocco di a=2
, il b
verrebbe ordinato in ordine crescente (secondo le specifiche dell'indice), in modo che la query find({a:2}).sort({b:1})
può essere soddisfatto da:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2
trova({a:2}).sort({b:-1})
Poiché l'indice può essere percorso avanti o indietro, è stata seguita una procedura simile, con una piccola svolta alla fine:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block backward to satisfy
2 | 2 <-- find({a:2}).sort({b:-1})
2 | 3 <--
3 | 1
3 | 2
Il fatto che l'indice possa essere percorso avanti o indietro è il punto chiave che abilita la query find({a:2}).sort({b:-1})
per poter utilizzare l'indice {a:1, b:1}
.
Spiegazione del pianificatore di query
Puoi vedere cosa pianifica il pianificatore di query utilizzando db.collection.explain().find(....)
. Fondamentalmente se vedi uno stage
di COLLSCAN
, nessun indice è stato utilizzato o può essere utilizzato per la query. Vedi spiega i risultati
per i dettagli sull'output del comando.