Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

Tipi di indici in Cloud Firestore

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

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 richiesti.

Questa pagina descrive i due tipi di indici utilizzati da Cloud Firestore, gli indici a campo singolo e gli indici compositi .

Un indice dietro ogni query

Se non esiste alcun indice per una query, la maggior parte dei database esegue la scansione del contenuto elemento per elemento, un processo lento che rallenta ancora di più man mano che il database cresce. Cloud Firestore garantisce prestazioni di query elevate utilizzando gli indici per tutte le query. Di conseguenza, le prestazioni della query dipendono dalle dimensioni del set di risultati e non dal numero di elementi nel database.

Meno gestione degli indici, più sviluppo di app

Cloud Firestore include funzionalità che riducono il tempo necessario per la gestione degli indici. Gli indici necessari per le query più elementari vengono creati automaticamente per te. Durante l'utilizzo e il test della tua app, Cloud Firestore ti aiuta a identificare e creare indici aggiuntivi richiesti dalla tua app.

Tipi di indici

Cloud Firestore utilizza due tipi di indici: a campo singolo e compositi . Oltre al numero di campi indicizzati, gli indici a campo singolo e compositi differiscono nel modo in cui li gestisci.

Indici a campo singolo

Un indice a campo singolo memorizza una mappatura ordinata di tutti i documenti in una raccolta che contiene un campo specifico. Ciascuna voce in un indice a campo singolo registra il valore di un documento per un campo specifico e la posizione del documento nel database. Cloud Firestore utilizza questi indici per eseguire molte query di base. Puoi gestire gli indici a campo singolo configurando le impostazioni di indicizzazione automatica e le esenzioni dall'indice del database.

Indicizzazione automatica

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

  • Per ogni campo non array e non mappa, Cloud Firestore definisce due indici a campo singolo nell'ambito della raccolta , uno in modalità ascendente e uno in modalità discendente.

  • Per ogni campo della mappa, Cloud Firestore crea un indice crescente nell'ambito della raccolta e un indice decrescente per ogni sottocampo non matrice e non mappa nella mappa.

  • Per ogni campo dell'array in un documento, Cloud Firestore crea e mantiene un indice contenente l'array nell'ambito della raccolta.

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

Esenzioni dall'indice a campo singolo

Puoi esentare un campo dalle impostazioni di indicizzazione automatica creando un'esenzione dall'indice a campo singolo. Un'esenzione dall'indicizzazione sovrascrive le impostazioni dell'indice automatico a livello di database. Un'esenzione può abilitare un indice a campo singolo che le impostazioni di indicizzazione automatica altrimenti disabiliterebbero o disabiliterebbero un indice a campo singolo che l'indicizzazione automatica abiliterebbe altrimenti. Per i casi in cui le esenzioni possono essere utili, vedere le migliori pratiche di indicizzazione .

Se crei un'esenzione dall'indice a campo singolo per un campo mappa, i sottocampi della mappa ereditano tali impostazioni. È tuttavia possibile definire esenzioni dall'indice a campo singolo per sottocampi specifici. Se elimini un'esenzione per un sottocampo, il sottocampo erediterà le impostazioni di esenzione del padre, se esistono, o le impostazioni a livello di database se non esistono esenzioni padre.

Per creare e gestire esenzioni per indici a campo singolo, consulta Gestione degli indici in Cloud Firestore .

Indici compositi

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

Cloud Firestore utilizza indici compositi per supportare le query non già supportate da indici a campo singolo.

Cloud Firestore non crea automaticamente indici compositi come fa per gli indici a campo singolo a causa dell'elevato numero di possibili combinazioni di campi. Invece, Cloud Firestore ti aiuta a identificare e creare gli indici compositi richiesti mentre crei la tua app.

Se si tenta la query precedente senza prima creare l'indice richiesto, Cloud Firestore restituisce un messaggio di errore contenente un collegamento che è possibile seguire per creare l'indice mancante. Ciò si verifica ogni volta che si tenta una query non supportata da un indice. Puoi anche definire e gestire gli indici compositi manualmente utilizzando la console o l'interfaccia a riga di comando di Firebase . Per ulteriori informazioni sulla creazione e la gestione di indici compositi, vedere Gestione degli indici .

Modalità di indice e ambiti di query

Si configurano gli indici a campo singolo e compositi in modo diverso, ma entrambi richiedono la configurazione delle modalità di indice e degli ambiti di query per i propri indici.

Modalità indice

Quando si definisce un indice, si seleziona una modalità di indice per ogni campo indicizzato. La modalità di indice di ogni campo supporta specifiche clausole di query su quel campo. È possibile selezionare tra le seguenti modalità di indice:

Modalità indice Descrizione
Freccia ascendente_verso Supporta < , <= , == , >= , > , != , in e not-in , clausole di query sul campo e supporta l'ordinamento dei risultati in ordine crescente in base al valore di questo campo.
Freccia discendente_verso 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.
Array-contiene Supporta array-contains e array-contains-any clausole di query sul campo.

Ambiti della query

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

Ambito di raccolta
Cloud Firestore crea indici con ambito di raccolta per impostazione predefinita. Questi indici supportano query che restituiscono risultati da una singola raccolta.

Ambito del gruppo di raccolta
Un gruppo di raccolte include tutte le raccolte con lo stesso ID raccolta. Per eseguire una query del gruppo di raccolte che restituisce risultati filtrati o ordinati da un gruppo di raccolte, è necessario creare un indice corrispondente con ambito del gruppo di raccolte.

Esempio di indicizzazione

Creando automaticamente indici a campo singolo per te, Cloud Firestore consente alla tua applicazione di supportare rapidamente le query di database più basilari. Gli indici a campo singolo consentono di eseguire query semplici in base ai valori dei campi e ai comparatori < , <= , == , >= , > e in . Per i campi dell'array, consentono di eseguire query array-contains e array-contains-any .

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

ragnatela
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"] });

Presupponendo le impostazioni di indicizzazione automatica predefinite, Cloud Firestore aggiorna un indice a campo singolo ascendente per campo non array, un indice a campo singolo discendente per campo non array e un indice a campo singolo contenente array per il campo array. Ogni riga nella tabella seguente rappresenta una voce in un indice a campo singolo:

Collezione Campo indicizzato Ambito della query
città Collezione
città stato Collezione
città paese Collezione
città capitale Collezione
città popolazione Collezione
città Collezione
città stato il basso Collezione
città paese Collezione
città capitale Collezione
città popolazione Collezione
città regioni array-contains Collezione

Query supportate da indici a campo singolo

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

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

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

ragnatela
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 è necessario eseguire una query composta che utilizza un confronto di intervallo ( < , <= , > o >= ) o se è necessario eseguire l'ordinamento in base a un campo diverso, è necessario creare un indice composito per tale query.

L'indice che array-contains consente di interrogare il campo dell'array delle regions :

ragnatela
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 compositi

Cloud Firestore utilizza indici compositi per supportare query composte non già supportate da indici a campo singolo. Ad esempio, avresti bisogno di un indice composito per le seguenti query:

ragnatela
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 composito riportato di seguito. Poiché la query utilizza un'uguaglianza ( == o in ) per il campo country , è possibile utilizzare una modalità indice crescente o decrescente per questo campo. Per impostazione predefinita, le clausole di disuguaglianza applicano un ordinamento crescente in base al campo nella clausola di disuguaglianza.

Collezione Campi indicizzati Ambito della query
città (o ) paese, popolazione Collezione

Per eseguire le stesse query ma con un ordinamento decrescente, è necessario un indice composito aggiuntivo nella direzione decrescente per la population :

ragnatela
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")
Collezione Campi indicizzati Ambito della query
città paese, popolazione Collezione
città paese , popolazione Collezione

È inoltre necessario creare un indice composito per combinare una query array-contains array o array-contains-any con clausole aggiuntive.

ragnatela
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)
Collezione Campi indicizzati Ambito della query
città array-contiene tag, (o ) capitale Collezione

Query supportate dagli indici dei gruppi di raccolte

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

ragnatela
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 ambito di raccolta, è possibile eseguire query sulla raccolta di punti di landmarks di una singola città in base al campo category :

Collezione Campi indicizzati Ambito della query
punti di riferimento (o ). Collezione
ragnatela
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 in tutte le città. Per eseguire questa query sul gruppo di raccolte costituito da tutte le raccolte di punti di landmarks , è necessario abilitare un indice a campo singolo di landmarks di riferimento con ambito del gruppo di raccolte:

Collezione Campi indicizzati Ambito della query
punti di riferimento (o ). Gruppo di raccolta

Con questo indice abilitato, puoi interrogare il gruppo di raccolta dei landmarks di riferimento:

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

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

Per eseguire una query del gruppo di raccolte che restituisce risultati filtrati o ordinati, è necessario abilitare un corrispondente campo singolo o un indice composito con ambito del gruppo di raccolte. Le query del gruppo di raccolta che non filtrano o ordinano i risultati, tuttavia, non richiedono definizioni di indice aggiuntive.

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

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

Voci di indice

Gli indici configurati del progetto e la struttura di un documento determinano il numero di voci di indice per un documento. Le voci dell'indice vengono conteggiate ai fini del limite di conteggio delle voci dell'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

  • nome_città ASC
  • nome_città DESC
  • temperature.estate ASC
  • temperature.estate DESC
  • temperature.inverno ASC
  • temperature.inverno DESC
  • quartieri Array Contiene (ASC e DESC)

Indici compositi

  • nome_città ASC, quartieri ARRAY
  • nome_città DESC, quartieri ARRAY

Voci di indice

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

Indice Dati indicizzati
Voci di indice a campo singolo
nome_città ASC nome_città: "San Francisco"
nome_città DESC nome_città: "San Francisco"
temperature.estate ASC temperature.estive: 67
temperature.estate DESC temperature.estive: 67
temperature.inverno ASC temperature.inverno: 55
temperature.inverno DESC temperature.inverno: 55
quartieri Array Contiene ASC quartieri: "Missione"
quartieri Array Contiene DESC quartieri: "Missione"
quartieri Array Contiene ASC quartieri: "Centro"
quartieri Array Contiene DESC quartieri: "Centro"
quartieri Array Contiene ASC quartieri: "Marina"
quartieri Array Contiene DESC quartieri: "Marina"
Voci di indice composite
nome_città ASC, quartieri ARRAY nome_città: "San Francisco", quartieri: "Mission"
nome_città ASC, quartieri ARRAY nome_città: "San Francisco", quartieri: "Centro"
nome_città ASC, quartieri ARRAY nome_città: "San Francisco", quartieri: "Marina"
nome_città DESC, quartieri ARRAY nome_città: "San Francisco", quartieri: "Mission"
nome_città DESC, quartieri ARRAY nome_città: "San Francisco", quartieri: "Centro"
nome_città DESC, quartieri ARRAY nome_città: "San Francisco", quartieri: "Marina"

Indici e prezzi

Gli indici contribuiscono ai costi di archiviazione della tua applicazione. Per ulteriori informazioni su come viene calcolata la dimensione di archiviazione per gli indici, vedere Dimensione voce di indice .

Sfruttare la fusione degli indici

Sebbene Cloud Firestore utilizzi 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 , Cloud Firestore può riutilizzare gli indici esistenti. Cloud Firestore può unire gli indici per semplici filtri di uguaglianza per creare gli indici compositi necessari per query di uguaglianza più grandi.

Puoi ridurre i costi di indicizzazione identificando le situazioni in cui puoi trarre vantaggio dall'unione degli indici. Ad esempio, immagina una raccolta di restaurants per un'app di valutazione dei ristoranti:

  • ristoranti

    • burgerthyme

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

Ora, immagina che questa app utilizzi query come quelle seguenti. Si noti che l'app utilizza combinazioni di clausole di uguaglianza per category , city e editors_pick ordinando sempre in base a star_rating crescente :

ragnatela
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:

Collezione Campi indicizzati Ambito della query
ristoranti categoria , Collezione
ristoranti città, star_rating Collezione
ristoranti categoria , città, star_rating Collezione
ristoranti categoria , città, editors_pick, star_rating Collezione

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

Collezione Campi indicizzati Ambito della query
ristoranti categoria , Collezione
ristoranti città, star_rating Collezione
ristoranti editors_pick, star_rating Collezione

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

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

Limiti di indicizzazione

I seguenti limiti si applicano agli indici. Per tutte le quote e limiti, vedere Quote e limiti .

Limite Particolari
Numero massimo di indici compositi per un database 200
Numero massimo di configurazioni a campo singolo per un database

200

Sono consentite un totale di 200 configurazioni a livello di campo. Una configurazione di campo può contenere più configurazioni per lo stesso campo. Ad esempio, un'esenzione dall'indicizzazione a campo singolo e un criterio TTL sullo stesso campo contano come configurazione di un campo verso il limite.

Numero massimo di voci di indice per ciascun documento

40.000

Il numero di voci dell'indice è la somma di quanto segue per un documento:

  • Il numero di voci di indice a campo singolo
  • Il numero di voci dell'indice composito

Per vedere come Cloud Firestore trasforma un documento e una serie di indici in voci di indice, consulta questo esempio di conteggio delle voci di indice .

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

7,5 KiB

Per vedere come Cloud Firestore calcola la dimensione della voce dell'indice, consulta la dimensione della voce dell'indice .

Somma massima delle dimensioni delle voci dell'indice di un documento

8 MiB

La dimensione totale è la somma di quanto segue per un documento:

  • La somma delle dimensioni delle voci dell'indice a campo singolo di un documento
  • La somma delle dimensioni delle voci dell'indice composito 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 coinvolgono valori di campo troncati possono restituire risultati incoerenti.

    Migliori pratiche di indicizzazione

    Per la maggior parte delle app, puoi fare affidamento sull'indicizzazione automatica e sui collegamenti ai messaggi di errore per gestire i tuoi indici. Tuttavia, potresti voler aggiungere esenzioni a campo singolo nei seguenti casi:

    Caso Descrizione
    Campi di stringhe di grandi dimensioni

    Se si dispone di un campo stringa che spesso contiene valori di stringa lunghi che non si utilizzano per eseguire query, è possibile ridurre i costi di archiviazione esentando il campo dall'indicizzazione.

    Elevate velocità di scrittura su una raccolta contenente documenti con valori sequenziali

    Se indicizzi un campo che aumenta o diminuisce in sequenza tra i documenti di una raccolta, ad esempio un timestamp, la velocità di scrittura massima nella raccolta è di 500 scritture al secondo. Se non esegui query in base al campo con valori sequenziali, puoi esentare il campo dall'indicizzazione per aggirare questo limite.

    In un caso d'uso IoT con una velocità 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 sui campi TTL è abilitata per impostazione predefinita e può influire sulle prestazioni a velocità di traffico più elevate. Come procedura consigliata, aggiungi esenzioni a campo singolo per i campi TTL.

    Matrice o campi mappa di grandi dimensioni

    Matrici di grandi dimensioni o campi mappa possono avvicinarsi al limite di 40.000 voci di indice per documento. Se non si esegue una query in base a un campo di matrice o mappa di grandi dimensioni, è necessario esentarlo dall'indicizzazione.