Ottimizza le prestazioni delle query

Per risolvere i problemi relativi alle query lente, utilizza Spiegazione query 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 fase 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 completi 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 select(...) per restituire solo i campi richiesti o remove_fields(...) per eliminare i campi eccessivamente grandi. 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, ciò consente anche alla query di essere completamente coperta dalla scansione dell'indice, evitando la necessità di recuperare i documenti dallo spazio di archiviazione principale.

Utilizza gli indici

Segui queste istruzioni 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 indice e i campi indice dell'indice.

Identifica un indice migliore

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 recupera ed elimina ancora 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 Creare indici.

Se viene utilizzato un indice per una query, ma il motore di query esegue ancora 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.

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à dei vincoli di 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.

Forza una scansione dell'indice o della tabella

Quando esegui query su Firestore in modalità Native, utilizza automaticamente tutti gli indici che potrebbero rendere la query più efficiente. Di conseguenza, non devi specificare un indice per le query. Tuttavia, per le query che sono fondamentali per il tuo carico di lavoro, ti consigliamo di utilizzare l'opzione forceIndex per prestazioni più coerenti.

In alcuni casi, Firestore in modalità Native potrebbe scegliere un indice che causa un aumento della latenza delle query. Se hai seguito i passaggi per la risoluzione dei problemi relativi alle regressioni delle prestazioni e hai confermato che è opportuno provare un indice diverso per la query, puoi specificare l'indice utilizzando l'opzione forceIndex.

Puoi utilizzare l'opzione forceIndex in qualsiasi fase di input delle operazioni della pipeline per sostituire il piano di query predefinito di Firestore in modalità Native e specificare un indice da utilizzare o per forzare una scansione della tabella.

Forza un indice specifico

Per forzare la query a utilizzare un indice specifico, fornisci l'ID indice come stringa all'opzione forceIndex. Puoi trovare l'ID indice nella console o nei messaggi di errore.

L'esempio seguente forza il pianificatore a utilizzare l'indice con ID CICAgOi36pgK:

// Force Planner to use Index ID CICAgOi36pgK
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" })
  .limit(100)

Ecco alcuni casi d'uso per forzare un indice specifico:

  • Testare le prestazioni di indici diversi.
  • Assicurarsi che per una query venga utilizzato un indice specifico e noto come ottimale.
  • Sostituire l'ottimizzatore quando la scelta predefinita non è ottimale per una query specifica.

Se l'indice specificato non viene trovato, la query non riesce.

Forza una scansione della tabella

Una scansione della tabella legge i documenti nella raccolta o nel gruppo di raccolte senza utilizzare indici secondari. Per forzare una scansione della tabella, imposta forceIndex su primary.

L'esempio seguente forza una scansione della tabella:

// Force Planner to only do a Full-Table Scan
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "primary" })
  .limit(100)

Puoi utilizzare una scansione della tabella nei seguenti casi:

  • Per raccolte molto piccole in cui il sovraccarico dell'indice non è giustificato.
  • Per le query che accedono alla maggior parte dei documenti di una raccolta.
  • Per il debug e i confronti delle prestazioni.

Utilizza forceIndex con Spiegazione query

Puoi utilizzare Spiegazione query, in particolare con l'opzione analyze, per osservare gli effetti di forceIndex:

  • Verifica che Firestore in modalità Native abbia utilizzato l'indice specificato in forceIndex controllando i nodi foglia dell'albero di esecuzione per l'ID indice.
  • Verifica che nel piano venga visualizzato un nodo TableScan quando utilizzi forceIndex: "primary".
  • Confronta le metriche sulle prestazioni, come la latenza, i documenti sottoposti a scansione e le voci di indice sottoposte a scansione, con e senza forceIndex per ottimizzare le prestazioni delle query.

Best practice per forceIndex

Sebbene forceIndex fornisca un maggiore controllo sull'esecuzione delle query, l'ottimizzatore di query di Firestore in modalità Native è in genere efficiente per la maggior parte dei casi d'uso. Tieni presente le seguenti best practice quando utilizzi forceIndex:

  • Utilizza forceIndex con giudizio. Se noti prestazioni non ottimali con il piano di query predefinito, utilizza Spiegazione query per diagnosticare il problema prima di forzare un indice.
  • Quando utilizzi forceIndex, assicurati di testare le query con volumi di dati realistici per comprenderne le caratteristiche di prestazioni e costi.
  • Evita di utilizzare forceIndex: "primary" su raccolte di grandi dimensioni negli ambienti di produzione.