Presentazione del nuovo gestore di Studio 3T 인덱스
Volete sapere qual è il modo più rapido per scoprire quali indici avete su una raccolta o per crearne facilmente di nuovi? Provate il nuovo e migliorato 인덱스 Manager, dove è possibile nascondere e nascondere gli indici con un semplice clic, eliminando l'attesa per la ricostruzione degli indici. Potete vedere a colpo d'occhio la frequenza di utilizzo dei vostri indici. È anche possibile confrontare gli indici su database diversi.
Provate gratuitamente Studio 3TCosa sono gli indici in MongoDB e perché ne abbiamo bisogno?
Gli indici rendono più efficiente l'interrogazione dei dati. Senza indici, MongoDB esegue una scansione della collezione che legge tutti i documenti della collezione per determinare se i dati corrispondono alle condizioni specificate nella query. Gli indici limitano il numero di documenti che MongoDB legge e con gli indici giusti è possibile migliorare le prestazioni. Gli indici memorizzano il valore di un campo o di un insieme di campi, ordinati in base al valore del campo.
Visualizzazione di 인덱스 Manager
Per visualizzare gli indici di una raccolta, individuare la raccolta nell'albero delle connessioni ed espanderla. È possibile espandere la sezione Indici per visualizzare i nomi 인덱스 :

Per visualizzare 인덱스 Manager, fare doppio clic sulla voce Indici nella parte superiore della sezione Indici.
인덱스 Manager visualizza un elenco di tutti gli indici della raccolta:

Per visualizzare i campi di 인덱싱된 e il loro ordine, fare clic sulla freccia nel campo Nome:

인덱스 dimensione
Per ottenere le migliori prestazioni, assicurarsi che tutti gli indici su tutte le collezioni siano presenti nella RAM del server MongoDB, per evitare di leggere gli indici dal disco. In alcuni casi, gli indici memorizzano solo i valori recenti nella RAM; per ulteriori informazioni, consultare la documentazione di MongoDB. Il campo Dimensione mostra la dimensione di ogni 인덱스 nella raccolta selezionata. La dimensione totale di 인덱스 (somma di tutti gli indici) per la raccolta è mostrata nell'angolo in basso a destra di 인덱스 Manager.
인덱스 utilizzo
Usage mostra quante volte è stato utilizzato 인덱스 da quando è stato creato 인덱스 o dall'ultimo riavvio del server.
인덱스 Manager visualizza le informazioni sull'uso solo se l'utente ha i privilegi per il comando $indexStats di MongoDB. Per ulteriori informazioni sulle statistiche di 인덱스 , consultare la documentazione di MongoDB.
Se un 인덱스 non viene utilizzato, è meglio eliminarlo, per eliminare i costi di mantenimento del 인덱스 quando i valori dei campi vengono aggiornati e lo spazio su disco.
Aggiunta di un 인덱스
Nella struttura delle connessioni, fare clic con il pulsante destro del mouse su una raccolta, quindi selezionare Aggiungi 인덱스.

Nella finestra di dialogo Aggiungi 인덱스, digitare il nome di 인덱스 nella casella 인덱스 nome. Se si lascia vuota la casella 인덱스 nome, Studio 3T crea un nome 인덱스 predefinito, basato sui nomi dei campi selezionati e sul tipo 인덱스 .
Aggiungere i campi richiesti al proprio 인덱스. Per farlo, selezionare il campo dall'elenco 인덱싱된 dei campi, quindi selezionare l'ordine (1 asc o -1 desc) o il tipo di 인덱스. Per saperne di più sui tipi e sulle proprietà di 인덱스 , vedere i tipi di MongoDB 인덱스 e le proprietà di MongoDB 인덱스 . Fare clic su Aggiungi campo.
Per impostazione predefinita, MongoDB costruisce gli indici in primo piano, impedendo tutte le operazioni di lettura e scrittura sul database durante la creazione di 인덱스 . Per consentire le operazioni di lettura e scrittura durante la creazione di , selezionare la casella di controllo Crea in background. 인덱스 Per consentire alle operazioni di lettura e scrittura di continuare a costruire gli indici 인덱스, selezionare la casella Crea in background. In questo modo le dimensioni di 인덱스 sono meno compatte e la creazione richiede più tempo.
Tuttavia, nel corso del tempo le dimensioni convergeranno come se si fosse costruito 인덱스 in primo piano. Per ulteriori informazioni sulla costruzione degli indici, consultare la documentazione di MongoDB.
Una volta terminata l'aggiunta dei campi al sito 인덱스 , fare clic su Create 인덱스.
MongoDB 인덱스 tipi di file
Indici a campo singolo
Quando si specificano i campi 인덱싱된 , si applica un ordine per ogni campo. In un campo singolo 인덱스, l'ordine non è importante perché MongoDB può attraversare i dati in entrambe le direzioni.
Indici composti
Gli indici composti specificano più campi 인덱싱된 . L'ordine in cui si specificano i campi è importante. MongoDB consiglia di seguire la regola ESR (Equality, Search, Range):
- Per prima cosa, aggiungere i campi contro i quali vengono eseguite le query di uguaglianza, ovvero le corrispondenze esatte su un singolo valore
- Successivamente, aggiungere i campi che riflettono l'ordine di ordinamento della query
- Infine, aggiungere i campi per i filtri di intervallo
Indici a più chiavi
Gli indici a più chiavi sono utilizzati per i campi che contengono array. È sufficiente specificare il campo che contiene l'array e MongoDB crea automaticamente una chiave 인덱스 per ogni elemento dell'array.
Indici di testo
Gli indici di testo supportano ricerche su campi che sono stringhe o array di elementi stringa. È possibile creare un solo testo 인덱스 per collezione. Un testo 인덱스 può contenere più campi.
인덱스 versione: esistono tre versioni, di cui la 3 è quella predefinita.
Lingua predefinita: la lingua predefinita è l'inglese. La lingua selezionata determina le regole utilizzate per analizzare le radici delle parole (suffissazione) e definisce le stop words che vengono filtrate. In inglese, ad esempio, le radici dei suffissi includono -ing e -ed, mentre le stop words includono the e a.
Sostituzione della lingua: specificare un nome di campo diverso per sostituire il campo della lingua.
Pesi dei campi: per ogni campo di 인덱싱된 , MongoDB moltiplica il numero di corrispondenze per il peso e somma i risultati. MongoDB utilizza questa somma per calcolare un punteggio per il documento. Selezionare un campo dall'elenco, specificarne il peso nella casella e fare clic su Aggiungi campo. Il peso predefinito del campo è 1.
Indici jolly
Gli indici wildcard supportano le query in cui i nomi dei campi sono sconosciuti, ad esempio in strutture di dati arbitrarie definite dall'utente in cui lo schema è dinamico. Un indice non jolly 인덱스 supporta solo le query sui valori delle strutture di dati definite dall'utente. Gli indici wildcard filtrano tutti i campi corrispondenti.
Per aggiungere un carattere jolly 인덱스 su tutti i campi per ogni documento di una raccolta, selezionare $** (tutti i campi) nell'elenco 인덱싱된 fields:

Indici geospaziali
Indici 2d
Gli indici 2d sono utilizzati per i dati memorizzati come punti su un piano bidimensionale. Gli indici 2d sono destinati alle coppie di coordinate legacy in MongoDB 2.2 e precedenti. Limite inferiore e limite superiore consentono di specificare un intervallo di posizione, invece delle impostazioni predefinite di -180 (incluso) per la longitudine e 180 (non incluso) per la latitudine. Precisione in bit consente di impostare la dimensione in bit dei valori di posizione, fino a 32 bit di precisione. L'impostazione predefinita è di 26 bit, pari a circa 60 centimetri di precisione, quando si utilizza l'intervallo di posizione predefinito.
Sfera 2d
Gli indici 2d sphere supportano le query che calcolano le geometrie su una sfera simile alla terra.
Geo pagliaio
Gli indici geoHaystack migliorano le prestazioni delle query che utilizzano una geometria piatta. Gli indici geoHaystack sono stati deprecati in MongoDB 4.4 e rimossi in MongoDB 5.0. Gli indici geoHaystack creano bucket di documenti della stessa area geografica. È necessario specificare la dimensione del bucket. Ad esempio, una dimensione del bucket pari a 5 crea un 인덱스 che raggruppa i valori di posizione che si trovano entro 5 unità dalla longitudine e dalla latitudine indicate. La dimensione del bucket determina anche la granularità di 인덱스.
Proprietà di MongoDB 인덱스
Indici unici
Gli indici univoci impediscono l'inserimento di documenti se esiste già un documento che contiene quel valore per il campo 인덱싱된 .
Indici sparsi
Gli indici sparsi saltano i documenti che non contengono il campo 인덱싱된 , a meno che il valore del campo non sia nullo. Gli indici sparsi non contengono tutti i documenti dell'insieme.
Indici nascosti
Gli indici nascosti sono nascosti dal piano di query. Questa opzione imposta l'indice 인덱스 come nascosto quando viene creato. È possibile impostare l'indice 인덱스 come non nascosto nel gestore 인덱스 ; per ulteriori informazioni, vedere Nascondere un indice 인덱스.
Indici TTL
Gli indici TTL sono indici a campo singolo che fanno scadere i documenti e indicano a MongoDB di eliminare i documenti dal database dopo un determinato periodo di tempo. Il campo 인덱싱된 deve essere di tipo data. Inserire il tempo di scadenza in secondi.
Indici parziali
Gli indici parziali includono solo i documenti che soddisfano un'espressione di filtro.
Indici senza distinzione tra maiuscole e minuscole
Gli indici case-insensitive supportano le query che ignorano le maiuscole e le minuscole quando confrontano le stringhe. L'uso di un 인덱스 case-insensitive non influisce sui risultati di una query. Per utilizzare 인덱스, le query devono specificare la stessa collazione.
Si definiscono indici non sensibili alle maiuscole e alle minuscole usando la collazione. La collazione consente di specificare regole specifiche della lingua per il confronto delle stringhe, come ad esempio le regole per gli accenti. È possibile specificare l'ordinamento a livello di collezione o di 인덱스 . Se un insieme ha una collazione definita, tutti gli indici la ereditano, a meno che non si specifichi una collazione personalizzata.
Per specificare una fascicolazione a livello di 인덱스 , selezionare la casella Usa fascicolazione personalizzata. L'impostazione Locale è obbligatoria e determina le regole della lingua. Impostare Forza su 1 o 2 per una collazione senza distinzione tra maiuscole e minuscole. Tutte le altre impostazioni sono facoltative e i valori predefiniti variano a seconda del locale specificato. Per ulteriori informazioni sulle impostazioni di fascicolazione, consultare la documentazione di MongoDB.
Lasciare cadere un 인덱스
Gli indici non utilizzati hanno un impatto sulle prestazioni di un database perché MongoDB deve mantenere 인덱스 ogni volta che i documenti vengono inseriti o aggiornati. La colonna Usage di 인덱스 Manager mostra quante volte è stato utilizzato un 인덱스 .
Prima di eliminare un 인덱스, si dovrebbe testare il supporto delle query da parte di 인덱스 nascondendolo. Se si osserva una diminuzione delle prestazioni, si deve togliere 인덱스, in modo che le query possano utilizzarlo di nuovo.
Non è possibile eliminare l'_id predefinito 인덱스 che MongoDB crea quando si aggiunge una nuova collezione.
Per abbandonare un sito 인덱스, eseguire una delle seguenti operazioni:
- nella struttura delle connessioni, fare clic con il tasto destro del mouse su 인덱스 e selezionare Drop 인덱스.
- nell'albero delle connessioni, selezionare 인덱스 e premere Ctrl + Backspace (Windows) o fn + Canc (Mac).
- selezionare 인덱스 in 인덱스 Manager e fare clic sul pulsante Drop 인덱스.
- fare clic con il tasto destro del mouse su 인덱스 in 인덱스 Manager e selezionare Drop 인덱스.
Per eliminare più di un 인덱스, selezionare gli indici richiesti nella struttura delle connessioni, fare clic con il pulsante destro del mouse e selezionare Elimina indici.
Modifica di un 인덱스
La modifica di un 인덱스 consente di modificare un 인덱스 esistente, ad esempio per cambiare i campi del 인덱싱된 . 인덱스 Manager elimina il file 인덱스 e ricrea il file 인덱스 con le modifiche specificate.
Per modificare un sito 인덱스, eseguire una delle seguenti operazioni per aprire la finestra di dialogo Modifica 인덱스:
- nella struttura delle connessioni, fare clic con il tasto destro del mouse su 인덱스 e selezionare Edit 인덱스.
- nell'albero delle connessioni, selezionare il sito 인덱스 e premere il tasto Invio.
- selezionare il sito 인덱스 nella Gestione 인덱스 e fare clic sul pulsante Modifica 인덱스.
- fare clic con il tasto destro del mouse su 인덱스 in 인덱스 Manager e selezionare Edit 인덱스.
Apportare le modifiche richieste e fare clic su Drop and recreate 인덱스.
Se l'unica modifica apportata a 인덱스 è quella di nascondere o nascondere 인덱스, non è necessario che 인덱스 Manager elimini e ricrei 인덱스, quindi si fa clic su Applica modifiche per apportare questa modifica.
Visualizzazione dei dettagli di 인덱스
È possibile visualizzare una versione di sola lettura dei dettagli di 인덱스 , per evitare di modificare accidentalmente le impostazioni.
Per visualizzare i dettagli di un sito 인덱스, eseguire una delle seguenti operazioni:
- selezionare il sito 인덱스 in 인덱스 Manager e fare clic sul pulsante Visualizza dettagli.
- fare clic con il pulsante destro del mouse su 인덱스 in 인덱스 Manager e selezionare Visualizza dettagli.
Nascondere un 인덱스
È possibile nascondere un 인덱스 dal piano di query. Nascondere un 인덱스 permette di valutare l'impatto dell'abbandono di un 인덱스. Nascondere un 인덱스 evita di dover abbandonare il 인덱스 e di crearlo di nuovo. È possibile confrontare le prestazioni delle query con e senza 인덱스 eseguendo la query con 인덱스 e poi nascondendo 인덱스 ed eseguendo nuovamente la query.
Quando si nasconde un 인덱스, le sue caratteristiche sono ancora valide, ad esempio gli indici univoci continuano ad applicare vincoli univoci ai documenti e gli indici TTL continuano a far scadere i documenti. Il 인덱스 nascosto continua a consumare spazio su disco e memoria, quindi se non migliora le prestazioni, si dovrebbe prendere in considerazione la possibilità di eliminare il 인덱스.
Gli indici nascosti sono supportati da MongoDB 4.4 o superiore. Assicurarsi che featureCompatibilityVersion sia impostato su 4.4 o superiore.
Per nascondere un sito 인덱스, eseguire una delle seguenti operazioni:
- nell'albero delle connessioni, fare clic con il pulsante destro del mouse su 인덱스 e selezionare Nascondi 인덱스. Il sito 인덱스 viene contrassegnato come nascosto.
- selezionare 인덱스 nella Gestione 인덱스 e fare clic sul pulsante Nascondi 인덱스. La colonna Proprietà di 인덱스 Manager mostra che 인덱스 è nascosto.
- fare clic con il tasto destro del mouse su 인덱스 in 인덱스 Manager e selezionare Hide 인덱스.
Per nascondere un sito 인덱스, eseguire una delle seguenti operazioni:
- nella struttura delle connessioni, fare clic con il tasto destro del mouse su 인덱스 e selezionare Unhide 인덱스.
- selezionare il sito 인덱스 nella Gestione 인덱스 e fare clic sul pulsante Nascondi 인덱스.
- fare clic con il tasto destro del mouse su 인덱스 in 인덱스 Manager e selezionare Unhide 인덱스.
Copiare un 인덱스
È possibile copiare un 인덱스 da un database e incollarne le proprietà in un altro database.
Per copiare un sito 인덱스, eseguire una delle seguenti operazioni:
- nella struttura delle connessioni, fare clic con il tasto destro del mouse su 인덱스 e selezionare Copia 인덱스.
- selezionare il sito 인덱스 in 인덱스 Manager e fare clic sul pulsante Copia.
- Fare clic con il tasto destro del mouse su 인덱스 nella Gestione 인덱스 e selezionare Copia 인덱스.
Per incollare il sito 인덱스, nella struttura delle connessioni, fare clic con il pulsante destro del mouse sulla raccolta di destinazione e selezionare Incolla 인덱스.
Per copiare più di un 인덱스, selezionare gli indici richiesti nella struttura di connessione, fare clic con il pulsante destro del mouse e selezionare Copia indici. Nella struttura delle connessioni, fare clic con il pulsante destro del mouse sulla collezione di destinazione e selezionare Incolla indici.
Usare gli indici di MongoDB (esercitazione)
Sebbene sia possibile memorizzare una grande quantità di informazioni in un database MongoDB, è necessaria una strategia di indicizzazione efficace per ottenere in modo rapido ed efficiente le informazioni necessarie.
In questo tutorial, illustrerò alcune delle basi dell'uso degli indici di MongoDB con semplici query, tralasciando gli aggiornamenti e gli inserimenti.
Questo vuole essere un approccio pratico, con solo la teoria sufficiente per consentire di provare gli esempi. L'intenzione è quella di permettere al lettore di usare solo la shell, anche se è molto più facile usare la GUI di MongoDB che ho usato, Studio 3T.
Un'introduzione agli indici di MongoDB
Quando MongoDB importa i dati in una raccolta, crea una chiave primaria che viene applicata da 인덱스.
Ma non può indovinare gli altri indici necessari, perché non è in grado di prevedere il tipo di ricerche, ordinamenti e aggregazioni che si vorranno fare su questi dati.
Fornisce solo un identificatore unico per ogni documento della collezione, che viene mantenuto in tutti gli indici successivi. MongoDB non consente gli heap. - dati non indicizzati legati tra loro solo da puntatori avanti e indietro.
MongoDB consente di creare indici aggiuntivi simili a quelli presenti nei database relazionali, che richiedono una certa dose di amministrazione.
Come per altri sistemi di database, esistono indici speciali per i dati sparsi, per la ricerca nel testo o per la selezione di informazioni spaziali.
Ogni query o aggiornamento utilizzerà in genere un solo 인덱스 se ne è disponibile uno adatto. Un 인덱스 può di solito aiutare le prestazioni di qualsiasi operazione sui dati, ma questo non è sempre il caso.
Si potrebbe essere tentati di provare l'approccio "a pioggia", creando molti indici diversi, in modo da assicurarsi che ce ne sia uno adatto, ma l'aspetto negativo è che ogni 인덱스 utilizza risorse e deve essere mantenuto dal sistema ogni volta che i dati cambiano.
Se si esagera con gli indici, questi arriveranno a dominare le pagine di memoria e a causare un eccessivo I/O su disco. La cosa migliore è un numero ridotto di indici altamente efficaci.
È probabile che una raccolta di dimensioni ridotte si inserisca nella cache, quindi il lavoro di fornitura degli indici e di messa a punto delle query non sembra avere molta influenza sulle prestazioni complessive.
Tuttavia, quando le dimensioni dei documenti aumentano e il numero di documenti cresce, il lavoro si fa sentire. Il vostro database scalerà bene.
Creare un database di prova
Per illustrare alcune delle basi di 인덱스 , caricheremo 70.000 clienti in MongoDB da un file JSON. Ogni documento registra il nome, l'indirizzo, il numero di telefono, i dati della carta di credito e le "note della pratica" dei clienti. Queste ultime sono state generate da numeri casuali.
Questo caricamento può essere fatto da mongoimport o da uno strumento come Studio 3T.
Specificare la collazione nelle raccolte di MongoDB
Prima di creare una raccolta, è necessario considerare la fascicolazione, il modo in cui vengono eseguite le ricerche e gli ordinamenti (la fascicolazione non è supportata prima di MongoDB 3.4).
Quando vedete le stringhe in ordine, volete vedere le minuscole ordinate dopo le maiuscole o l'ordinamento deve ignorare le maiuscole? Un valore rappresentato da una stringa viene considerato diverso a seconda dei caratteri in maiuscolo? Come ci si comporta con i caratteri accentati? Per impostazione predefinita, le raccolte hanno un ordinamento binario, che probabilmente non è quello richiesto nel mondo del commercio.
Per scoprire l'eventuale collation utilizzata per la propria raccolta, è possibile utilizzare questo comando (qui per la collezione "Clienti").
db.getCollectionInfos({name: 'Customers'})

Questo mostra che ho impostato la collezione Customers con la collazione 'en'.
Se scorro l'output della shell, vedo che tutti gli indici di MongoDB hanno la stessa collation, il che è positivo.
Purtroppo, non è possibile modificare la collation di una raccolta esistente. È necessario creare la collezione prima di aggiungere i dati.
Ecco come creare una raccolta 'Clienti' con una collazione inglese. In Studio 3T, è possibile definire la collazione sia tramite l'interfaccia utente che tramite IntelliShell.
Ecco la scheda di fascicolazione della finestra "Aggiungi nuova fascicolazione", raggiungibile facendo clic con il tasto destro del mouse sul nome del database e facendo clic su "Aggiungi nuova fascicolazione ...".

È possibile ottenere la stessa cosa in IntelliShell utilizzando il comando:
db.createCollection("Customers", {collation:{locale:"en",strength:1}})

In alternativa, è possibile aggiungere informazioni sulla collazione a qualsiasi ricerca, ordinamento o confronto di stringhe.
Secondo la mia esperienza, è più ordinato, sicuro e facile da modificare se lo si fa a livello di collezione. Se la collazione di 인덱스 non corrisponde alla collazione della ricerca o dell'ordinamento che si fa, MongoDB non può usare 인덱스.
Se si importa un documento, è meglio che il suo ordine naturale sia preordinato in base alla fascicolazione specificata, nell'ordine dell'attributo più 인덱싱된 comune. In questo modo la chiave primaria viene "raggruppata", in quanto 인덱스 può avere meno blocchi di pagine da visitare per ogni ricerca della chiave 인덱스 e il sistema otterrà un tasso di risposta molto più alto.
Comprendere lo schema
Una volta caricati i dati del mock di esempio, è possibile visualizzarne lo schema semplicemente esaminando il primo documento
db.Customers.find({}).limit(1);
In Studio 3T, è possibile visualizzarlo nella scheda Collezione:

Indici MongoDB per query semplici
Velocizzare una query molto semplice
Ora eseguiamo una semplice query sul nostro database appena creato per trovare tutti i clienti il cui cognome è "Johnston".
Vogliamo eseguire una proiezione o selezionare 'Nome' e 'Cognome', ordinati per 'Cognome'. La riga "_id" : NumberInt(0), significa semplicemente "non restituire l'ID".
use customers; db.Customers.find({ "Name.Last Name" : "Johnston" }, { "_id" : NumberInt(0), "Name.First Name" : NumberInt(1), "Name.Last Name" : NumberInt(1) }).sort({ "Name.Last Name" : NumberInt(1) });

Una volta accertato che la query restituisce il risultato corretto, possiamo modificarla per restituire le statistiche di esecuzione.
use customers; use customers; db.Customers.find({ "Name.Last Name" : "Johnston" }, { "_id" : NumberInt(0), "Name.First Name" : NumberInt(1), "Name.Last Name" : NumberInt(1) }).sort({ "Name.Last Name" : NumberInt(1) }).explain("executionStats");
Secondo le statistiche di esecuzione di 'Explain', questo richiede 59 Ms sulla mia macchina (ExecutionTimeMillis). Si tratta di una COLLSCAN, il che significa che non c'è 인덱스 disponibile, quindi mongo deve analizzare l'intero insieme.
Questo non è necessariamente un male con una collezione ragionevolmente piccola, ma quando le dimensioni aumentano e più utenti accedono ai dati, è meno probabile che l'insieme entri nella memoria paginata e l'attività su disco aumenterà.
Il database non scalerà bene se è costretto a eseguire una grande percentuale di COLLSCAN. È una buona idea ridurre al minimo le risorse utilizzate dalle query eseguite di frequente.
È ovvio che se 인덱스 riduce il tempo impiegato, è probabile che coinvolga Nome.Cognome.
Cominciamo con questo, rendendolo un 인덱스 ascendente, poiché vogliamo che l'ordinamento sia ascendente:
db.Customers.createIndex( {"Name.Last Name" : 1 },{ name: "LastNameIndex"} )
Ora ci vogliono 4 Ms sul mio computer (ExecutionTimeMillis). Si tratta di un IXSCAN (una scansione di 인덱스 per ottenere le chiavi) seguito da un FETCH (per recuperare i documenti).
Possiamo migliorare questo aspetto perché la query deve ottenere il nome.
Se aggiungiamo Name.First Name nel sito 인덱스, il motore del database può utilizzare il valore presente nel sito 인덱스 , anziché effettuare il passaggio aggiuntivo di prelievo dal database.
db.Customers.dropIndex("LastNameIndex") db.Customers.createIndex( { "Name.Last Name" : 1,"Name.First Name" : 1 }, { name: "LastNameCompoundIndex"} )
Con questo sistema, l'interrogazione richiede meno di 2 Ms.
Poiché 인덱스 ha "coperto" la query, MongoDB è stato in grado di soddisfare le condizioni della query e di restituire i risultati utilizzando solo le chiavi di 인덱스 , senza nemmeno dover esaminare i documenti della raccolta per restituire i risultati. (Se nel piano di esecuzione si vede uno stadio IXSCAN che non è figlio di uno stadio FETCH, allora 인덱스 ha "coperto" la query).
Si noterà che il nostro ordinamento era l'ovvio ordinamento crescente, A-Z. Lo abbiamo specificato con un 1 come valore per l'ordinamento. Cosa succede se il risultato finale deve essere da Z-A (discendente), specificato da -1? Non c'è alcuna differenza rilevabile con questo breve set di risultati.
Sembra un progresso. Ma cosa succede se si sbaglia il sito 인덱스 ? Questo può causare problemi.
Se si cambia l'ordine dei due campi in 인덱스 in modo che Nome.Nome venga prima di Nome.Cognome, il tempo di esecuzione sale a 140 Ms, un aumento enorme.
Questo sembra strano, perché 인덱스 ha effettivamente rallentato l'esecuzione, tanto da richiedere più del doppio del tempo impiegato con il solo 인덱스 primario predefinito (tra i 40 e i 60 Ms). MongoDB controlla certamente le possibili strategie di esecuzione per trovarne una buona, ma a meno che non si sia fornito un 인덱스 adatto, è difficile che riesca a selezionare quella giusta.
Cosa abbiamo imparato finora?
Sembrerebbe che le query semplici traggano il massimo vantaggio dagli indici che sono coinvolti nei criteri di selezione e con la stessa collazione.
Nel nostro esempio precedente, abbiamo illustrato una verità generale sugli indici di MongoDB: se il primo campo di 인덱스 non fa parte dei criteri di selezione, non è utile eseguire la query.
Velocizzare le interrogazioni non SARGable
Cosa succede se abbiamo due criteri, uno dei quali prevede una corrispondenza di stringhe all'interno del valore?
use customers; db.Customers.find({ "Name.Last Name" : "Wiggins", "Addresses.Full Address" : /.*rutland.*/i });
Vogliamo trovare un cliente di nome Wiggins che vive a Rutland. Ci vogliono 50 Ms senza alcun supporto 인덱스.
Se escludiamo il nome dalla ricerca, il tempo di esecuzione raddoppia.
use customers; db.Customers.find({ "Addresses.Full Address" : /.*rutland.*/i });
Se ora introduciamo un 인덱스 composto che inizia con il nome e poi aggiunge l'indirizzo, scopriamo che la ricerca è stata così rapida che sono stati registrati 0 Ms.
Questo perché l'indice ha permesso a MongoDB di trovare solo quei 52 Wiggins nel database e di effettuare la ricerca solo attraverso quegli indirizzi. Questo è abbastanza buono!
Cosa succede se invertiamo i due criteri? Sorprendentemente, il criterio "spiega" riporta 72 Ms.
Sono entrambi criteri validi specificati nella query, ma se si utilizza quello sbagliato la query è inutile, con una perdita di 20 Ms.
La ragione della differenza è ovvia. Il sito 인덱스 potrebbe impedire una scansione di tutti i dati, ma non può aiutare la ricerca, poiché si tratta di un'espressione regolare.
I principi generali sono due.
Una ricerca complessa deve ridurre il più possibile i candidati alla selezione con il primo elemento dell'elenco degli indici. Il termine "cardinalità" indica questo tipo di selettività. Un campo a bassa cardinalità, come il sesso, è molto meno selettivo del cognome.
Nel nostro esempio, il cognome è abbastanza selettivo da essere la scelta più ovvia per il primo campo elencato in 인덱스, ma non molte query sono così ovvie.
La ricerca offerta dal primo campo di un 인덱스 utilizzabile deve essere SARGabile. Questo significa che il campo 인덱스 deve essere ARGumentabilealla ricerca.
Nel caso della ricerca della parola "rutland", il termine di ricerca non si riferiva direttamente a ciò che era presente nel sito 인덱스 e all'ordine di ordinamento del sito 인덱스.
Siamo riusciti a usarlo in modo efficace solo perché abbiamo usato l'ordine 인덱스 per convincere MongoDB a trovare i venti probabili "Wiggins" nel database e poi a usare la copia dell'indirizzo completo in 인덱스 piuttosto che il documento stesso.
In questo modo è possibile ricercare questi venti indirizzi completi in modo molto rapido, senza nemmeno dover recuperare i dati dai venti documenti. Infine, con la chiave primaria contenuta in 인덱스, è possibile recuperare molto rapidamente il documento corretto dalla raccolta.
Includere un array incorporato in una ricerca
Proviamo a eseguire una query leggermente più complessa.
Vogliamo effettuare una ricerca sul cognome e sull'indirizzo e-mail del cliente.
La nostra raccolta di documenti consente al nostro "cliente" di avere uno o più indirizzi e-mail. Questi si trovano in un array incorporato.
Vogliamo solo trovare una persona con un determinato cognome, "Barker" nel nostro esempio, e un determinato indirizzo e-mail, "[email protected]" nel nostro esempio.
Vogliamo restituire solo l'indirizzo e-mail corrispondente e i suoi dettagli (quando è stato registrato e quando è diventato non valido). Eseguiamo questa operazione dalla shell ed esaminiamo le statistiche di esecuzione.
db.Customers.find({ "Name.Last Name" : "Barker", "EmailAddresses.EmailAddress" : "[email protected]" }, { "_id" : NumberInt(0), "EmailAddresses.$.EmailAddress" : NumberInt(1), "Full Name" : NumberInt(1) });
Che dà:
{ "Full Name" : "Mr Cassie Gena Barker J.D.", "EmailAddresses" : [ { "EmailAddress" : "[email protected]", "StartDate" : "2016-05-02", "EndDate" : "2018-01-25" } ] }
Questo ci dice che Cassie Barker ha avuto l'indirizzo e-mail [email protected] dall'11 gennaio 2016 al 25 gennaio 2018. Quando abbiamo eseguito la query, ci sono voluti 240 ms perché non c'era nessun 인덱스 utile (ha esaminato tutti i 40000 documenti in una COLLSCAN).
Possiamo creare un sito 인덱스 per aiutare questo aspetto:
db.Customers.createIndex( { "Name.Last Name" : 1 },{ name: "Nad"} );
Questo 인덱스 ha ridotto il tempo di esecuzione a 6ms.
Il Nad 인덱스 che era l'unico disponibile per la collezione era solo sul campo Name.Last Name.
Per la fase di input è stata utilizzata la strategia IXSCAN, che ha restituito molto rapidamente 33 documenti corrispondenti, andando avanti.
Quindi ha filtrato i documenti corrispondenti per recuperare l'array EmailAddresses per l'indirizzo che è stato poi restituito nella fase di proiezione. In totale sono stati utilizzati 3 Ms, a fronte dei 70 Ms necessari.
L'aggiunta di altri campi nel sito 인덱스 non ha avuto alcun effetto percepibile. Il primo campo di 인덱스 è quello che determina il successo.
E se volessimo solo sapere chi utilizza un determinato indirizzo e-mail?
db.Customers.find({ "EmailAddresses.EmailAddress" : "[email protected]" }, { "_id" : NumberInt(0), "EmailAddresses.$.EmailAddress" : NumberInt(1), "Full Name" : NumberInt(1) });
In questo caso, un 인덱스 sul campo emailAddress fa miracoli. Senza un 인덱스 adatto, viene eseguito un COLLSCAN che richiede circa 70 Ms sul mio server di sviluppo.
Con un sito 인덱스...
db.Customers.createIndex( { "EmailAddresses.EmailAddress" : 1 },{ name: "AddressIndex"} )
... il tempo impiegato è già troppo rapido per essere misurato.
Si sarà notato che, per 인덱스 un campo che contiene un valore di un array, MongoDB crea una chiave 인덱스 per ogni elemento dell'array.
Potremmo renderlo ancora più veloce se assumessimo che gli indirizzi e-mail sono unici (in questi dati di spoof non lo sono, e nella vita reale è un'ipotesi pericolosa!).
Possiamo anche usare 인덱스 per "coprire" il recupero del campo "Nome completo", in modo che MongoDB possa recuperare questo valore da 인덱스 piuttosto che recuperarlo dal database, ma la percentuale di tempo risparmiata sarà minima.
Uno dei motivi per cui i recuperi di 인덱스 funzionano così bene è che tendono a ottenere tassi di risposta nella cache molto migliori rispetto alle scansioni dell'intero insieme. Tuttavia, se tutto l'insieme può essere inserito nella cache, una scansione dell'insieme si avvicinerà alla velocità di 인덱스 .
Utilizzo delle aggregazioni
Vediamo quali sono i nomi più popolari nel nostro elenco clienti, utilizzando un'aggregazione. Forniremo un 인덱스 su "Nome.Cognome".
db.Customers.aggregate({$project :{"Name.Last Name": 1}}, {$group :{_id: "$Name.Last Name", count : {$sum: 1}}}, {$sort : {count : -1}}, {$limit:10} );
Quindi, nella nostra top ten, abbiamo molti membri della famiglia Snyder:
{ "_id" : "Snyder", "count" : 83 } { "_id" : "Baird", "count" : 81 } { "_id" : "Evans", "count" : 81 } { "_id" : "Andrade", "count" : 81 } { "_id" : "Woods", "count" : 80 } { "_id" : "Burton", "count" : 79 } { "_id" : "Ellis", "count" : 77 } { "_id" : "Lutz", "count" : 77 } { "_id" : "Wolfe", "count" : 77 } { "_id" : "Knox", "count" : 77 }
Questo ha richiesto solo 8 Ms nonostante l'esecuzione di un COLLSCAN, perché l'intero database poteva essere conservato nella memoria cache.
Utilizza lo stesso piano di query anche se si esegue l'aggregazione su un campo non indicizzato. (Elisha, Eric, Kim e Lee sono i nomi di battesimo più diffusi).
Mi chiedo quali siano i nomi di battesimo che tendono ad attirare il maggior numero di note sulla loro scheda.
db.Customers.aggregate( {$group: {_id: "$Name.First Name", NoOfNotes: {$avg: {$size: "$Notes"}}}}, {$sort : {NoOfNotes : -1}}, {$limit:10} );
Nei miei dati di spoof, sono le persone chiamate Charisse a ricevere il maggior numero di note. In questo caso sappiamo che un COLLSCAN è inevitabile, poiché il numero di note cambierà in un sistema attivo. Alcuni database consentono indici sulle colonne calcolate, ma in questo caso non sarebbero utili.
{ "_id" : "Charisse", "NoOfNotes" : 1.793103448275862 } { "_id" : "Marian", "NoOfNotes" : 1.72 } { "_id" : "Consuelo", "NoOfNotes" : 1.696969696969697 } { "_id" : "Lilia", "NoOfNotes" : 1.6666666666666667 } { "_id" : "Josephine", "NoOfNotes" : 1.65625 } { "_id" : "Willie", "NoOfNotes" : 1.6486486486486487 } { "_id" : "Charlton", "NoOfNotes" : 1.6458333333333333 } { "_id" : "Kristi", "NoOfNotes" : 1.6451612903225807 } { "_id" : "Cora", "NoOfNotes" : 1.64 } { "_id" : "Dominic", "NoOfNotes" : 1.6363636363636365 }
Le prestazioni delle aggregazioni possono essere migliorate con un indice perché possono coprire l'aggregazione. Solo gli operatori della pipeline $match e $sort possono sfruttare direttamente un indice, e solo se si trovano all'inizio della pipeline.
Per generare i dati di prova in questa esercitazione è stato utilizzato SQL Data Generator.
Conclusioni
- Quando si sviluppa una strategia di indicizzazione per MongoDB, si scopre che ci sono diversi fattori da prendere in considerazione, come la struttura dei dati, il modello di utilizzo e la configurazione dei server del database.
- MongoDB generalmente utilizza un solo 인덱스 quando esegue una query, sia per la ricerca che per l'ordinamento; e se può scegliere una strategia, campionerà i migliori indici candidati.
- La maggior parte delle raccolte di dati ha alcuni candidati abbastanza buoni per gli indici, che probabilmente differenziano chiaramente tra i documenti della raccolta e che probabilmente sono popolari nell'esecuzione delle ricerche.
- È una buona idea essere parsimoniosi con gli indici, perché hanno un costo minore in termini di risorse. Il pericolo maggiore è quello di dimenticare ciò che è già presente, anche se fortunatamente non è possibile creare indici duplicati in MongoDB.
- È comunque possibile creare diversi indici composti che hanno una costituzione molto simile. Se un 인덱스 non viene utilizzato, è meglio abbandonarlo.
- Gli indici composti sono molto utili per supportare le query. Utilizzano il primo campo per effettuare la ricerca e poi usano i valori degli altri campi per restituire i risultati, invece di doverli ricavare dai documenti. Supportano anche ordinamenti che utilizzano più di un campo, purché nell'ordine giusto.
- Affinché gli indici siano efficaci per i confronti tra stringhe, devono utilizzare la stessa collazione.
- Vale la pena di tenere sotto controllo le prestazioni delle query. Oltre a usare i valori restituiti da explain(), conviene cronometrare le query e verificare se ci sono query che durano a lungo, attivando il profiling ed esaminando le query lente. Spesso è sorprendentemente facile trasformare la velocità di tali query fornendo il giusto 인덱스.
Domande frequenti sugli indici di MongoDB
Gli indici non rallentano le query di MongoDB. Tuttavia, quando un documento viene creato, aggiornato o cancellato, anche gli indici associati devono essere aggiornati e ciò influisce sulle prestazioni di scrittura.
Si dovrebbe evitare l'indicizzazione in MongoDB quando si ha una raccolta di piccole dimensioni o quando si ha una raccolta che non viene interrogata frequentemente.
Poiché MongoDB crea un file per ogni 인덱스, un numero eccessivo di indici può influire sulle prestazioni. Quando il motore di archiviazione di MongoDB si avvia, apre tutti i file, quindi le prestazioni diminuiscono se c'è un numero eccessivo di indici.
Fare doppio clic sulla voce Indici nell'albero delle connessioni per le raccolte che si desidera confrontare, in modo da avere due schede di 인덱스 Manager. Fare clic con il pulsante destro del mouse sulla parte superiore di una delle schede e selezionare Dividi verticalmente. Le schede vengono visualizzate affiancate in modo da poter confrontare gli indici dei due database.
Eseguire la query nella scheda Collections e aprire la scheda Explain per vedere una rappresentazione visiva di come MongoDB ha elaborato la query. Se la query ha usato un 인덱스, si vedrà una 인덱스 scansione altrimenti si vedrà una scansione della scansione della raccolta altrimenti si vedrà una fase di scansione della raccolta. Per informazioni sull'uso della scheda Spiega, consultare l'articolo della Knowledge Base Spiegazione visiva | Spiegazione di MongoDB, visualizzata.
Individuare la raccolta nella struttura delle connessioni e fare doppio clic sulla sezione Indici per aprire 인덱스 Manager. 인덱스 Manager visualizza le informazioni sulle dimensioni di ogni 인덱스 collezione.
Individuare la raccolta nell'albero delle connessioni. Gli indici sono elencati nella sezione Indici sotto il nome della raccolta. Fare doppio clic su 인덱스 per visualizzare una versione di sola lettura dei suoi dettagli. I dettagli sulle dimensioni e sull'utilizzo sono visualizzati nella scheda 인덱스 Manager nella scheda Collezioni.
Quando MongoDB crea una raccolta 인덱스, blocca temporaneamente la raccolta, impedendo tutte le operazioni di lettura e scrittura sui dati in quella raccolta. MongoDB crea i metadati di 인덱스 , una tabella temporanea di chiavi e una tabella temporanea di violazioni di vincoli. Il blocco sulla raccolta viene quindi declassato e le operazioni di lettura e scrittura sono consentite periodicamente. MongoDB esegue la scansione dei documenti della raccolta e scrive nelle tabelle temporanee. Mentre MongoDB costruisce il sito 인덱스, ci sono diverse fasi del processo in cui la collezione è esclusivamente bloccata. Per tutti i dettagli sul processo di compilazione, si veda il file MongoDB per tutti i dettagli del processo di compilazione, si veda la documentazione di MongoDB. Quando 인덱스 è costruito, MongoDB aggiorna i metadati di 인덱스 e rilascia il blocco.
In un ambiente di produzione, se la raccolta ha un carico di scrittura elevato, si dovrebbe prendere in considerazione la creazione di 인덱스 durante i periodi di riduzione delle operazioni, ad esempio durante i periodi di manutenzione, in modo che le prestazioni non siano influenzate e il tempo di creazione di 인덱스 sia più breve.
Quando si crea un 인덱스 in MongoDB, la cifra 1 specifica che si vuole creare il 인덱스 in ordine crescente. Per creare un 인덱스 in ordine decrescente, si usa -1.
Per saperne di più sugli indici di MongoDB
Siete interessati a saperne di più sugli indici di MongoDB? Consultate questi articoli della knowledge base correlati:
Come ottimizzare le query di MongoDB con find() e gli indici
Come usare MongoDB Profiler e explain() per trovare le query lente
Spiegazione visiva | Spiegazione di MongoDB, visualizzata
Articolo aggiornato da Kirsty Burgess il 03/05/2023
Kirsty è la nostra responsabile delle parole. Quando non lavora a 3T, potete trovare Kirsty mentre cerca di fare cose sciocche come pose a triangolo con gli scarponi da sci, o mentre fa casino in cucina con tutti i barattoli della credenza delle spezie, o sulla collina dietro casa sua mentre cammina e guarda gli alti edifici all'orizzonte.