Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Panoramica dell'indicizzazione

Gli indici sono un fattore importante nelle prestazioni di un database. Proprio come l'indice di un libro che mappa gli argomenti in un libro ai numeri di pagina, un indice di database mappa gli elementi in un database alle loro posizioni nel database. Quando invii una query a un database, il database può utilizzare un indice per cercare rapidamente le posizioni degli elementi che hai richiesto.

In questa pagina vengono descritti i due tipi di indici utilizzati da Firestore, gli indici a campo singolo e gli indici composti.

Un indice dietro ogni query

Se per una query non esiste un indice, la maggior parte dei database esegue la scansione degli elementi di ciascun contenuto, un processo lento che rallenta ancora di più con il crescere del database. Firestore garantisce prestazioni di query elevate utilizzando indici per tutte le query. Di conseguenza, le prestazioni delle query dipendono dalle dimensioni del set di risultati e non dal numero di elementi nel database.

Meno gestione dell'indice, più sviluppo di app

Firestore include funzionalità che riducono la quantità di tempo necessaria per gestire gli indici. Gli indici necessari per le query di base vengono creati automaticamente. Durante l'utilizzo e il test dell'app,Firestore ti consente di identificare e creare ulteriori indici richiesti dall'app.

Tipi di indice

Firestore utilizza due tipi di indici: campo singolo e composito. Oltre al numero di campi indicizzati, gli indici a campo singolo e composti variano in base alla modalità di gestione.

Indici a campo singolo

Un indice a campo singolo archivia una mappatura ordinata di tutti i documenti in una raccolta che contengono un campo specifico. Ogni voce in un indice a campo singolo registra il valore di un documento per un campo specifico e la posizione del documento nel database. Firestore usa questi indici per eseguire molte query di base. Puoi gestire gli indici a campo singolo configurando le impostazioni di indicizzazione automatiche e le esenzioni dell'indice del tuo database.

Indicizzazione automatica

Per impostazione predefinita, Firestore mantiene automaticamente gli indici a campo singolo per ogni campo in un documento e ogni sottocampo in una mappa. Firestore utilizza le seguenti impostazioni predefinite per gli indici a campo singolo:

  • Per ogni campo non array e non mappa, Firestore definisce due indici a campo singolo collection-scope, uno in modalità crescente e uno in modalità decrescente.

  • Per ogni campo della mappa, Firestore crea un indice ascendente a livello di raccolta e un indice decrescente per ogni sottocampo non array e non mappa nella mappa.

  • Per ogni campo dell'array in un documento, Firestore crea e gestisce un indice contiene un array con ambito a livello di raccolta.

  • Gli indici a campo singolo con ambito del gruppo di raccolte non vengono gestiti per impostazione predefinita.

Esenzioni indice a campo singolo

Puoi escludere un campo dalle impostazioni di indicizzazione automatica creando un'esenzione di indice a campo singolo. Un'esenzione di indicizzazione sostituisce le impostazioni di indicizzazione automatica a livello di database. Un'esenzione può attivare un indice a campo singolo che altrimenti le impostazioni di indicizzazione automatica disattiverebbero o disabilitano un indice a campo singolo che altrimenti verrebbe abilitato. Per i casi in cui le esenzioni possono essere utili, consulta le best practice per l'indicizzazione.

Se crei un'esenzione per l'indice a campo singolo per un campo mappa, i sottocampi della mappa ereditano queste impostazioni. Tuttavia, puoi definire esenzioni per l'indice a campo singolo per sottocampi specifici. Se elimini un'esenzione per un sottocampo, quest'ultimo erediterà le impostazioni di esenzione del relativo padre, se esistenti, oppure le impostazioni a livello di database se non esistono esenzioni padre.

Per creare e gestire le esenzioni dell'indice a campo singolo, consulta Gestione degli indici in Firestore.

Indici composti

Un indice composto archivia una mappatura ordinata di tutti i documenti in una raccolta, in base a un elenco ordinato di campi da indicizzare.

Firestore utilizza indici composti per supportare le query non già supportate dagli indici a campo singolo.

Firestore non crea automaticamente indici composti come per gli indici a campo singolo a causa dell'elevato numero di possibili combinazioni di campi. Firestore ti aiuta invece a identificare e creare indici composti obbligatori durante la creazione della tua applicazione.

Se provi la query sopra senza creare l'indice richiesto, Firestore restituisce un messaggio di errore contenente un link che puoi seguire per creare l'indice mancante. Questo si verifica ogni volta che provi una query non supportata da un indice. Puoi anche definire e gestire manualmente gli indici composti utilizzando la console o utilizzando l'interfaccia a riga di comando di Firebase. Per ulteriori informazioni sulla creazione e sulla gestione degli indici composti, consulta la sezione Gestire gli indici.

Modalità indice e ambiti di query

Configura gli indici a campo singolo e composito in modo diverso, ma entrambi richiedono la configurazione delle modalità dell'indice e degli ambiti di query per gli indici.

Modalità indice

Quando definisci un indice, devi selezionare una modalità di indicizzazione per ogni campo indicizzato. La modalità indice di ogni campo supporta clausole di query specifiche su quel campo. Puoi scegliere tra le seguenti modalità di indicizzazione:

Modalità Indice Descrizione
crescente Supporta clausole di query sul campo <, <=, ==, >=, >, !=, in e not-in e supporta l'ordinamento dei risultati in ordine crescente in base al valore di questo campo.
Decrescente Supporta le clausole di query <, <=, ==, >=, >, !=, in e not-in sul campo e supporta l'ordinamento dei risultati in ordine decrescente in base al valore di questo campo.
L'array contiene Supporta le clausole di query array-contains e array-contains-any sul campo.

Ambiti di query

Ogni ambito è limitato a una raccolta o a un gruppo di raccolte. Questo è noto come ambito di query dell'indice:

Ambito della raccolta
Firestore crea per impostazione predefinita indici con l'ambito della raccolta. Questi indici supportano le query che restituiscono risultati da una singola raccolta.

Ambito del gruppo di raccolte
Un gruppo di raccolte include tutte le collezioni con lo stesso ID raccolta. Per eseguire una query del gruppo di raccolte che restituisca risultati restituiti o ordinati da un gruppo di raccolte, devi creare un indice corrispondente con l'ambito del gruppo di raccolte.

Esempio di indicizzazione

Creando automaticamente gli indici a campo singolo, Firestore consente alla tua applicazione di supportare rapidamente le query di database di base. Gli indici a campo singolo consentono di eseguire query semplici basate sui valori dei campi e sui comparatori <, <=, ==, >=, > e in. Per i campi di array, consentono di eseguire query array-contains e array-contains-any.

Per illustrare, esamina i seguenti esempi dal punto di vista della creazione dell'indice. Il seguente snippet crea alcuni city documenti in una raccolta cities e imposta i campi name, state, country, capital, population e tags per ogni documento:

Web
var citiesRef = db.collection("cities");

citiesRef.doc("SF").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000,
    regions: ["west_coast", "norcal"] });
citiesRef.doc("LA").set({
    name: "Los Angeles", state: "CA", country: "USA",
    capital: false, population: 3900000,
    regions: ["west_coast", "socal"] });
citiesRef.doc("DC").set({
    name: "Washington, D.C.", state: null, country: "USA",
    capital: true, population: 680000,
    regions: ["east_coast"] });
citiesRef.doc("TOK").set({
    name: "Tokyo", state: null, country: "Japan",
    capital: true, population: 9000000,
    regions: ["kanto", "honshu"] });
citiesRef.doc("BJ").set({
    name: "Beijing", state: null, country: "China",
    capital: true, population: 21500000,
    regions: ["jingjinji", "hebei"] });

Presumendo le impostazioni di indicizzazione automatica predefinite, Firestore aggiorna un indice crescente di un campo singolo per campo non array, un indice decrescente di campo singolo per campo non array e un array contenente un indice a campo singolo per il campo array. Ogni riga della tabella seguente rappresenta una voce in un indice a campo singolo:

Raccolta Campo indicizzato Ambito di query
cities Nome Raccolta
cities Stato Raccolta
cities paese Raccolta
cities capitale Raccolta
cities popolazione Raccolta
cities Nome Raccolta
cities Stato Raccolta
cities paese Raccolta
cities capitale Raccolta
cities popolazione Raccolta
cities array-contains regioni Raccolta

Query supportate da indici a campo singolo

Utilizzando questi indici a campo singolo creati automaticamente, puoi eseguire query semplici come le seguenti:

Web
const stateQuery = citiesRef.where("state", "==", "CA");
const populationQuery = citiesRef.where("population", "<", 100000);
const nameQuery = citiesRef.where("name", ">=", "San Francisco");

Puoi anche creare query con in e uguaglianza composta (==):

Web
citiesRef.where('country', 'in', ["USA", "Japan", "China"])

// Compound equality queries
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA")
         .where("capital", "==", false)
         .where("state", "==", "CA")
         .where("population", "==", 860000)

Se devi eseguire una query composta che utilizza un confronto di intervalli (<, <=, > o >=) o se vuoi ordinare i dati in base a un campo diverso, devi creare un indice composto per tale query.

L'indice array-contains consente di eseguire query sul campo array regions:

Web
citiesRef.where("regions", "array-contains", "west_coast")
// array-contains-any and array-contains use the same indexes
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])

Query supportate da indici composti

Firestore utilizza indici composti per supportare le query composte non ancora supportate dagli indici a campo singolo. Ad esempio, ti servirà un indice composto per le seguenti query:

Web
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)
// in and == clauses use the same index
citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)

Queste query richiedono l'indice composto di seguito. Poiché la query utilizza un'uguaglianza (== o in) per il campo country, puoi utilizzare una modalità indice crescente o decrescente per questo campo. Per impostazione predefinita, le clausole di incompatibilità applicano un ordinamento crescente in base al campo nella clausola di incompatibilità.

Raccolta Campi indicizzati Ambito di query
cities (o ) paese, popolazione Raccolta

Per eseguire le stesse query ma con un ordinamento decrescente, devi avere un indice composto aggiuntivo nella direzione decrescente per population:

Web
citiesRef.where("country", "==", "USA").orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", "<", 3800000)
         .orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", ">", 690000)
         .orderBy("population", "desc")

citiesRef.where("country", "in", ["USA", "Japan", "China"])
         .where("population", ">", 690000)
         .orderBy("population", "desc")
Raccolta Campi indicizzati Ambito di query
cities paese, popolazione Raccolta
città paese, popolazione Raccolta

Devi inoltre creare un indice composto per combinare una query array-contains o array-contains-any con clausole aggiuntive.

Web
citiesRef.where("regions", "array-contains", "east_coast")
         .where("capital", "==", true)

// array-contains-any and array-contains use the same index
citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])
         .where("capital", "==", true)
Raccolta Campi indicizzati Ambito di query
cities Tag array-contiene, (o ) capitale Raccolta

Query supportate dagli indici dei gruppi di raccolte

Per dimostrare un indice con l'ambito del gruppo di raccolte, immagina di aggiungere una sottoraccolta landmarks ad alcuni dei documenti city:

Web
var citiesRef = db.collection("cities");

citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Bridge",
    category : "bridge" });
citiesRef.doc("SF").collection("landmarks").doc().set({
    name: "Golden Gate Park",
    category : "park" });

citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Gallery of Art",
    category : "museum" });
citiesRef.doc("DC").collection("landmarks").doc().set({
    name: "National Mall",
    category : "park" });

Utilizzando il seguente indice a campo singolo con l'ambito della raccolta, puoi eseguire query sulla raccolta di una singola città landmarks in base al campo category:

Raccolta Campi indicizzati Ambito di query
punti di riferimento Categoria (o ) Raccolta
Web
citiesRef.doc("SF").collection("landmarks").where("category", "==", "park")
citiesRef.doc("SF").collection("landmarks").where("category", "in", ["park", "museum"])

Ora, immagina di essere interessato a interrogare i punti di riferimento di tutte le città. Per eseguire questa query sul gruppo di raccolte che comprende tutte le raccolte landmarks, devi attivare un indice a campo singolo landmarks con l'ambito del gruppo di raccolte:

Raccolta Campi indicizzati Ambito di query
punti di riferimento Categoria (o ) Gruppo di raccolte

Se questo indice è abilitato, puoi eseguire query sul gruppo di raccolte landmarks:

Web
var landmarksGroupRef = db.collectionGroup("landmarks");

landmarksGroupRef.where("category", "==", "park")
landmarksGroupRef.where("category", "in", ["park", "museum"])

Per eseguire una query di un gruppo di raccolte che restituisce risultati filtrati o ordinati, devi attivare un indice a campo singolo o composito corrispondente con l'ambito del gruppo di raccolte. Le query dei gruppi di raccolte che non filtrano o ordinano i risultati, tuttavia, non richiedono definizioni di indice aggiuntive.

Ad esempio, puoi eseguire la seguente query del gruppo di raccolte senza attivare un indice aggiuntivo:

Web
db.collectionGroup("landmarks").get()

Voci dell'indice

Gli indici configurati dal tuo progetto e la struttura del documento determinano il numero di voci di indice per un documento. Le voci di indice vengono conteggiate per il limite di conteggio di voci di indice.

L'esempio seguente mostra le voci di indice di un documento.

Documento

/cities/SF

city_name : "San Francisco"
temperatures : {summer: 67, winter: 55}
neighborhoods : ["Mission", "Downtown", "Marina"]

Indici a campo singolo

  • città_nome_ASC
  • città_nome DESC
  • temperature.estate SC
  • temperature.summer DESC
  • temperature.inverno ASC
  • Descrizioni temperature.inverno
  • L'array di quartiere contiene (ASC e DESC)

Indici composti

  • City_name ASC, quartieri ARRAY
  • city_name DESC, quartieri ARRAY

Voci dell'indice

Questa configurazione di indicizzazione genera le seguenti 18 voci di indice per il documento:

Indice Dati indicizzati
Voci dell'indice a campo singolo
città_nome_ASC city_name: "San Francisco"
città_nome DESC city_name: "San Francisco"
temperature.estate SC temperature.estate: 67
temperature.summer DESC temperature.estate: 67
temperature.inverno ASC temperature.inverno: 55
Descrizioni temperature.inverno temperature.inverno: 55
L'array di quartiere contiene ASC quartieri: "Mission"
L'array di quartiere contiene DESC quartieri: "Mission"
L'array di quartiere contiene ASC quartieri: "Centro cittadino"
L'array di quartiere contiene DESC quartieri: "Centro cittadino"
L'array di quartiere contiene ASC quartieri: "Marina"
L'array di quartiere contiene DESC quartieri: "Marina"
Voci dell'indice composito
City_name ASC, quartieri ARRAY city_name: "San Francisco", quartieri: "Mission"
City_name ASC, quartieri ARRAY city_name: "San Francisco", quartieri: "Centro cittadino"
City_name ASC, quartieri ARRAY city_name: "San Francisco", quartieri: "Marina"
city_name DESC, quartieri ARRAY city_name: "San Francisco", quartieri: "Mission"
city_name DESC, quartieri ARRAY city_name: "San Francisco", quartieri: "Centro cittadino"
city_name DESC, quartieri ARRAY city_name: "San Francisco", quartieri: "Marina"

Indici e prezzi

Gli indici contribuiscono ai costi di archiviazione dell'applicazione. Per ulteriori informazioni su come vengono calcolate le dimensioni dello spazio di archiviazione per gli indici, consulta Dimensioni delle voci di indice.

Sfruttare l'unione di indici

Anche se Firestore utilizza un indice per ogni query, non richiede necessariamente un indice per query. Per le query con più clausole di uguaglianza (==) e, facoltativamente, una clausola orderBy, Firestore può riutilizzare i indici esistenti. Firestore può unire gli indici per semplici filtri di uguaglianza per creare gli indici composti necessari per le query di uguaglianza più grandi.

Puoi ridurre i costi di indicizzazione individuando le situazioni in cui puoi sfruttare l'unione di indici. Ad esempio, immagina una raccolta restaurants per un'app per la valutazione dei ristoranti:

  • ristoranti

    • hamburger

      name : "Burger Thyme"
      category : "burgers"
      city : "San Francisco"
      editors_pick : true
      star_rating : 4

Ora, supponiamo che questa app utilizzi query come quelle indicate di seguito. Tieni presente che l'app utilizza combinazioni di clausole di uguaglianza per category, city e editors_pick, sempre in ordine crescente di star_rating:

Web
db.collection("restaurants").where("category", "==", "burgers")
                            .orderBy("star_rating")

db.collection("restaurants").where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==" "San Francisco")
                            .where("editors_pick", "==", true )
                            .orderBy("star_rating")

Puoi creare un indice per ogni query:

Raccolta Campi indicizzati Ambito di query
ristoranti Categoria , star_rating Raccolta
ristoranti città, star_rating Raccolta
ristoranti Categoria , città, star_rating Raccolta
ristoranti Categoria , città, editor_pick, star_rating Raccolta

Come soluzione migliore, puoi ridurre il numero di indici sfruttando la capacità di Firestore di unire gli indici per le clausole di uguaglianza:

Raccolta Campi indicizzati Ambito di query
ristoranti Categoria , star_rating Raccolta
ristoranti città, star_rating Raccolta
ristoranti editor_pick, star_rating Raccolta

Non solo questo insieme di indici è più piccolo, ma supporta anche una query aggiuntiva:

Web
db.collection("restaurants").where("editors_pick", "==", true)
                            .orderBy("star_rating")

Limiti di indicizzazione

I seguenti limiti sono applicabili agli indici. Per tutte le quote e i limiti, consulta Quote e limiti.

Limite Dettagli
Numero massimo di indici composti per un database 200
Numero massimo di configurazioni a campo singolo per un database

200

Sono consentite 200 configurazioni a livello di campo in totale. Una configurazione di campo può contenere più configurazioni per lo stesso campo. Ad esempio, un'esenzione di indicizzazione a campo singolo e un criterio TTL nello stesso campo vengono conteggiati come una configurazione di campo ai fini del limite.

Numero massimo di voci di indice per ogni documento

40.000

Il numero di voci di indice corrisponde alla somma di quanto segue per un documento:

  • Numero di voci degli indici a campo singolo
  • Numero di voci degli indici composti

Per scoprire in che modo Firestore trasforma un documento e una serie di indici in voci di indice, vedi questo esempio di conteggio di voci di indice.

Numero massimo di campi in un indice composto 100
Dimensione massima di una voce di indice

7,5 KiB

Per scoprire in che modo Firestore calcola la dimensione di una voce di indice, vai alla pagina Dimensioni delle voci di indice.

Somma massima delle dimensioni delle voci di indice di un documento

8 MiB

La dimensione totale corrisponde alla somma di quanto segue per un documento:

  • Somma delle dimensioni delle voci degli indici a campo singolo di un documento
  • Somma delle dimensioni delle voci degli indici composti di un documento
  • Dimensione massima di un valore di campo indicizzato

    1500 byte

    I valori di campo superiori a 1500 byte vengono troncati. Le query che includono valori di campo troncati possono restituire risultati incoerenti.

    Best practice per l'indicizzazione

    Per la maggior parte delle app, l'indicizzazione automatica e i link ai messaggi di errore consentono di gestire gli indici. Tuttavia, puoi aggiungere esenzioni a campo singolo nei seguenti casi:

    Caso Descrizione
    Campi stringa di grandi dimensioni

    Se hai un campo stringa che spesso contiene valori stringa lunghi che non utilizzi per le query, puoi ridurre i costi di archiviazione esentando il campo dall'indicizzazione.

    Velocità di scrittura elevate in una raccolta contenente documenti con valori sequenziali

    Se indicizzi un campo che aumenta o diminuisce in modo sequenziale tra i documenti di una raccolta, ad esempio un timestamp, la frequenza di scrittura massima nella raccolta è di 500 scritture al secondo. Se non esegui query basate sul campo con valori sequenziali, puoi escludere il campo dall'indicizzazione per ignorare questo limite.

    In un caso d'uso IoT con una frequenza di scrittura elevata, ad esempio, una raccolta contenente documenti con un campo timestamp potrebbe avvicinarsi al limite di 500 scritture al secondo.

    Campi TTL

    Se utilizzi i criteri TTL (Time to Live), tieni presente che il campo TTL deve essere un timestamp. L'indicizzazione nei campi TTL è abilitata per impostazione predefinita e può influire sulle prestazioni a frequenze di traffico più elevate. Come best practice, aggiungi esenzioni a campo singolo per i campi TTL.

    Campi di matrici o mappe di grandi dimensioni

    I campi di grandi dimensioni o con mappa possono avvicinarsi al limite di 40.000 voci di indice per documento. Se non esegui query in base a un array o a un campo mappa di grandi dimensioni, devi esentarlo dall'indicizzazione.