Ottimizzare le prestazioni delle query

Per risolvere i problemi relativi alle query lente, utilizza Query Explain per ottenere il piano di esecuzione della query e il profilo di esecuzione di runtime. La sezione seguente descrive i passaggi che puoi eseguire per ottimizzare le prestazioni delle query a seconda del profilo di esecuzione:

Limita il numero di risultati

Utilizza il campo dei record restituiti nell'albero di esecuzione per verificare se la query restituisce molti documenti. Valuta la possibilità di limitare il numero di documenti restituiti utilizzando la clausola $limit. In questo modo si riducono le dimensioni dei byte serializzati dei risultati quando vengono restituiti ai client tramite la rete. Nei casi in cui il nodo Limit è preceduto da un nodo MajorSort, il motore di query può unire i nodi Limit e MajorSort e sostituire una materializzazione e un ordinamento in memoria con un ordinamento TopN, riducendo il requisito di memoria per la query.

Limita le dimensioni del documento dei risultati

Valuta la possibilità di limitare le dimensioni del documento restituito utilizzando la clausola $project per evitare di recuperare campi non necessari. In questo modo si riducono i costi di calcolo e di memoria per l'elaborazione dei risultati intermedi e le dimensioni dei byte serializzati dei risultati quando vengono restituiti ai client tramite la rete. Nei casi in cui tutti i campi a cui viene fatto riferimento nella query sono coperti da un indice normale (non multikey), la query può essere completamente coperta dalla scansione dell'indice, evitando la necessità di recuperare i documenti dallo spazio di archiviazione principale.

Utilizza gli indici

Segui le istruzioni riportate di seguito per configurare e ottimizzare gli indici.

Verifica se la query utilizza un indice

Puoi verificare se la query utilizza un indice controllando i nodi foglia nell'albero di esecuzione. Se il nodo foglia dell'albero di esecuzione è un nodo TableScan, significa che la query non utilizza un indice e sta eseguendo la scansione dei documenti dallo spazio di archiviazione principale. Se viene utilizzato un indice, il nodo foglia dell'albero di esecuzione visualizzerà l'ID dell'indice e i campi dell'indice.

Verifica se l'indice utilizzato può essere ottimizzato

Un indice è utile per una query se può ridurre il numero di documenti che il motore di query deve recuperare dallo spazio di archiviazione principale o se l'ordinamento dei campi può soddisfare il requisito di ordinamento della query.

Se viene utilizzato un indice per una query, ma il motore di query continua a recuperare e scartare molti documenti, come identificato da un nodo Scan che restituisce molti record seguito da un nodo Filter che restituisce pochi record, significa che il predicato della query soddisfatto utilizzando l'indice non è selettivo. Per creare un indice più adatto, consulta Crea indici.

Se per una query viene utilizzato un indice non multikey, ma il motore di query esegue comunque un riordinamento in memoria del set di risultati, come identificato da un nodo MajorSort nell'albero di esecuzione della query, significa che l'indice utilizzato non può essere utilizzato per soddisfare il requisito di ordinamento della query. Per creare un indice più adatto, consulta la sezione successiva.

Ottimizzazione delle query $lookup

Puoi ottimizzare le query $lookup aggiungendo indici alla raccolta from, in modo che l'operazione possa trovare in modo efficiente i documenti corrispondenti senza eseguire la scansione dell'intera raccolta.

$lookup con localField e foreignField

Se utilizzi le opzioni localField e foreignField nella fase $lookup, crea un indice su foreignField nella raccolta from.

$lookup con pipeline nidificate

Se utilizzi l'opzione pipeline nella fase $lookup con le fasi $match, crea un indice sui campi coinvolti nella raccolta esterna per evitare una scansione completa della raccolta:

  • Per le fasi $match con semantica di filtro (ad esempio {$match: {a: true}}), crea un indice sui campi coinvolti nella raccolta esterna (a).
  • Per le fasi $match con semantica di aggregazione che confronta un campo con un valore costante (ad esempio {$match: {$expr: {$gt: [a, 10]}}}) o con confronti di uguaglianza (eq o in) tra campi e variabili definiti in let (ad esempio {$match: {$expr: {$eq: [a, "$$a"]}}}), crea un indice sui campi coinvolti nella raccolta esterna. Tieni presente che l'indice multikey non verrà utilizzato nella pianificazione.

Crea indici

Segui la documentazione sulla gestione degli indici per creare gli indici. Per assicurarti che la query possa utilizzare gli indici, crea indici normali (non multikey) con i campi nel seguente ordine:

  1. Tutti i campi che verranno utilizzati negli operatori di uguaglianza. Per massimizzare la probabilità di riutilizzo tra le query, ordina i campi in ordine decrescente di occorrenza dei campi negli operatori di uguaglianza tra le query.
  2. Tutti i campi su cui verrà eseguito l'ordinamento (nello stesso ordine).
  3. Campi che verranno utilizzati negli operatori di intervallo o di disuguaglianza in ordine decrescente di selettività del vincolo della query.
  4. Campi che verranno restituiti come parte di una query nell'indice: l'inclusione di questi campi nell'indice consente all'indice di coprire la query ed evitare di dover recuperare il documento dallo spazio di archiviazione principale.

Per le query che prevedono il filtraggio e l'ordinamento dei campi array, valuta la possibilità di creare indici multikey.

Utilizza il suggerimento per la query

Se hai creato un indice più adatto per la query, ma il motore di query non lo utilizza, puoi sostituire la preferenza dell'indice del motore di query utilizzando un suggerimento per la query.

Per saperne di più sull'output di una query eseguita con Query Explain, consulta Riferimento all'esecuzione delle query.