获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

Procedure consigliate per Cloud Firestore

Utilizza le best practice elencate qui come riferimento rapido durante la creazione di un'applicazione che utilizza Cloud Firestore.

Posizione della banca dati

Quando crei l'istanza del database, seleziona la posizione del database più vicina agli utenti e alle risorse di calcolo. Gli hop di rete di vasta portata sono più soggetti a errori e aumentano la latenza delle query.

Per massimizzare la disponibilità e la durabilità della tua applicazione, seleziona una posizione in più aree geografiche e colloca le risorse di calcolo critiche in almeno due aree geografiche.

Seleziona una località regionale per costi inferiori, per una minore latenza di scrittura se la tua applicazione è sensibile alla latenza o per la co-ubicazione con altre risorse GCP .

ID documento

  • Evita gli ID documento . e ..
  • Evita di utilizzare / barre negli ID documento.
  • Non utilizzare ID documento che aumentano in modo monotono come:

    • Customer1 , Customer2 , Customer3 , ...
    • Product 1 , Product 2 , Product 3 , ...

    Tali ID sequenziali possono portare a hotspot che influiscono sulla latenza.

Nomi di campo

  • Evita i seguenti caratteri nei nomi dei campi perché richiedono caratteri di escape aggiuntivi:

    • . periodo
    • [ parentesi sinistra
    • ] parentesi quadra destra
    • * asterisco
    • ` apice inverso

Indici

  • Evitare di utilizzare troppi indici. Un numero eccessivo di indici può aumentare la latenza di scrittura e aumentare i costi di archiviazione per le voci di indice.

  • Tieni presente che l'indicizzazione di campi con valori crescenti in modo monotono, come i timestamp, può portare a hotspot che influiscono sulla latenza per le applicazioni con velocità di lettura e scrittura elevate.

Esenzioni dall'indice

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

Caso Descrizione
Grandi campi stringa

Se disponi di un campo stringa che contiene spesso 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 sequenza tra i documenti in una raccolta, come un timestamp, la velocità massima di scrittura 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 ignorare questo limite.

In un caso d'uso IoT con un'elevata velocità di scrittura, 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 tassi di traffico più elevati. Come best practice, aggiungi esenzioni a campo singolo per i tuoi campi TTL.

Matrice di grandi dimensioni o campi mappa

I campi matrice o mappa di grandi dimensioni possono avvicinarsi al limite di 40.000 voci di indice per documento. Se non stai eseguendo una query in base a un campo di matrice o mappa di grandi dimensioni, dovresti esentarlo dall'indicizzazione.

Operazioni di lettura e scrittura

  • Evitare di scrivere su un documento più di una volta al secondo. Per ulteriori informazioni, vedere Aggiornamenti a un singolo documento .

  • Utilizzare le chiamate asincrone, ove disponibili, anziché le chiamate sincrone. Le chiamate asincrone riducono al minimo l'impatto della latenza. Ad esempio, si consideri un'applicazione che necessita del risultato di una ricerca di documenti e dei risultati di una query prima di eseguire il rendering di una risposta. Se la ricerca e la query non hanno una dipendenza dati, non è necessario attendere in modo sincrono il completamento della ricerca prima di avviare la query.

  • Non utilizzare offset. Invece, usa i cursori . L'utilizzo di un offset evita solo di restituire i documenti saltati all'applicazione, ma questi documenti vengono comunque recuperati internamente. I documenti ignorati influiscono sulla latenza della query e all'applicazione vengono fatturate le operazioni di lettura necessarie per recuperarli.

Tentativi di transazione

Gli SDK e le librerie client di Cloud Firestore ritentano automaticamente le transazioni non riuscite per gestire gli errori temporanei. Se la tua applicazione accede a Cloud Firestore direttamente tramite le API REST o RPC anziché tramite un SDK, la tua applicazione dovrebbe implementare tentativi di transazione per aumentare l'affidabilità.

Aggiornamenti in tempo reale

Per le migliori prestazioni dell'ascoltatore di istantanee , mantieni i tuoi documenti piccoli e controlla la velocità di lettura dei tuoi clienti. Le seguenti raccomandazioni forniscono linee guida per ottimizzare le prestazioni. Il superamento di questi consigli può comportare un aumento della latenza delle notifiche.

Raccomandazione Particolari
Riduci il tasso di abbandono dell'ascoltatore di istantanee

Evita ascoltatori che si agitano frequentemente, soprattutto quando il tuo database è sottoposto a un carico di scrittura significativo

Idealmente, la tua applicazione dovrebbe configurare tutti i listener di snapshot richiesti subito dopo aver aperto una connessione a Cloud Firestore. Dopo aver configurato i listener di snapshot iniziali, dovresti evitare di aggiungere o rimuovere rapidamente listener di snapshot nella stessa connessione.

Per garantire la coerenza dei dati, Cloud Firestore deve eseguire il priming di ogni nuovo snapshot listener dai dati di origine e quindi aggiornarsi sulle nuove modifiche. A seconda della velocità di scrittura del database, questa può essere un'operazione costosa.

I tuoi snapshot listener possono riscontrare una maggiore latenza se aggiungi o rimuovi spesso snapshot listener ai riferimenti. In generale, un listener costantemente collegato offre prestazioni migliori rispetto al collegamento e allo scollegamento di un listener in quella posizione per la stessa quantità di dati. Per prestazioni ottimali, gli snapshot listener dovrebbero avere una durata di almeno 30 secondi. Se riscontri problemi di prestazioni dell'ascoltatore nella tua app, prova a monitorare gli ascolti e i non ascolti dell'app per determinare se potrebbero verificarsi troppo frequentemente.

Limita i listener di snapshot per client

100

Mantieni il numero di listener di istantanee per client al di sotto di 100.

Limita la velocità di scrittura della raccolta

1.000 operazioni/secondo

Mantieni la frequenza delle operazioni di scrittura per una singola raccolta al di sotto di 1.000 operazioni al secondo.

Limita la frequenza di push del singolo client

1 documento/secondo

Mantieni la velocità dei documenti inviati dal database a un singolo cliente al di sotto di 1 documento/secondo.

Limita la frequenza di push del client globale

1.000.000 documenti/secondo

Mantieni la velocità dei documenti inviati dal database a tutti i client al di sotto di 1.000.000 di documenti al secondo.

Questo è un limite morbido. Cloud Firestore non ti impedisce di superare questa soglia ma influisce notevolmente sulle prestazioni.

Limita il payload del singolo documento

10 KiB/secondo

Mantieni la dimensione massima del documento scaricato da un singolo cliente al di sotto di 10 KiB/secondo.

Limita il payload del documento globale

1 GiB/secondo

Mantieni la dimensione massima del documento scaricato su tutti i client al di sotto di 1 GiB/secondo.

Limita il numero di campi per documento

100

I tuoi documenti dovrebbero avere meno di 100 campi.

Comprendi i limiti standard di Cloud Firestore

Tieni presente i limiti standard per Cloud Firestore .

Prestare particolare attenzione al limite di 1 scrittura al secondo per i documenti e al limite di 1.000.000 di connessioni simultanee per database. Questi sono limiti flessibili che Cloud Firestore non ti impedisce di superare. Tuttavia, il superamento di questi limiti potrebbe influire sulle prestazioni, a seconda delle velocità totali di lettura e scrittura.

Progettare per la scala

Le procedure consigliate seguenti descrivono come evitare situazioni che creano problemi di contesa.

Aggiornamenti a un singolo documento

Mentre progetti la tua app, considera quanto velocemente la tua app aggiorna i singoli documenti. Il modo migliore per caratterizzare le prestazioni del tuo carico di lavoro è eseguire il test del carico. La velocità massima esatta con cui un'app può aggiornare un singolo documento dipende fortemente dal carico di lavoro. I fattori includono la velocità di scrittura, la contesa tra le richieste e il numero di indici interessati.

Un'operazione di scrittura di un documento aggiorna il documento e gli eventuali indici associati e Cloud Firestore applica l'operazione di scrittura in modo sincrono a un quorum di repliche. A velocità di scrittura sufficientemente elevate, il database inizierà a riscontrare contesa, latenza più elevata o altri errori.

Elevate velocità di lettura, scrittura ed eliminazione su un intervallo di documenti ristretto

Evita velocità di lettura o scrittura elevate per chiudere lessicograficamente i documenti, altrimenti la tua applicazione riscontrerà errori di contesa. Questo problema è noto come hotspotting e la tua applicazione può riscontrare hotspotting se esegue una delle seguenti operazioni:

  • Crea nuovi documenti a una velocità molto elevata e alloca i propri ID in modo monotono.

    Cloud Firestore alloca gli ID documento utilizzando un algoritmo di dispersione. Non dovresti riscontrare hotspotting durante le scritture se crei nuovi documenti utilizzando ID documento automatici.

  • Crea nuovi documenti a una velocità elevata in una raccolta con pochi documenti.

  • Crea nuovi documenti con un campo in aumento monotono, come un timestamp, a una velocità molto elevata.

  • Elimina i documenti in una raccolta a una velocità elevata.

  • Scrive nel database a una velocità molto elevata senza aumentare gradualmente il traffico.

Evita di saltare i dati cancellati

Evita le query che ignorano i dati eliminati di recente. Una query potrebbe dover ignorare un numero elevato di voci di indice se i primi risultati della query sono stati eliminati di recente.

Un esempio di un carico di lavoro che potrebbe dover ignorare molti dati eliminati è quello che tenta di trovare gli elementi di lavoro in coda meno recenti. La query potrebbe essere simile a:

docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
delete_batch.commit()

Ogni volta che questa query viene eseguita, esegue la scansione delle voci di indice per il campo created su tutti i documenti eliminati di recente. Questo rallenta le query.

Per migliorare le prestazioni, utilizza il metodo start_at per trovare il punto di partenza migliore. Per esempio:

completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
    {'created': completed_items.get('last_completed')}).order_by(
        'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
  last_completed = doc.get('created')

if last_completed:
  delete_batch.update(completed_items.reference,
                      {'last_completed': last_completed})
  delete_batch.commit()

NOTA: l'esempio precedente utilizza un campo in aumento monotono che è un anti-pattern per velocità di scrittura elevate.

Aumento del traffico

Dovresti aumentare gradualmente il traffico verso nuove raccolte o chiudere lessicograficamente i documenti per dare a Cloud Firestore il tempo sufficiente per preparare i documenti per l'aumento del traffico. Ti consigliamo di iniziare con un massimo di 500 operazioni al secondo per una nuova raccolta e quindi aumentare il traffico del 50% ogni 5 minuti. Allo stesso modo puoi aumentare il tuo traffico di scrittura, ma tieni a mente i limiti standard di Cloud Firestore . Assicurati che le operazioni siano distribuite in modo relativamente uniforme in tutta la gamma di tasti. Questa è chiamata la regola "500/50/5".

Migrazione del traffico verso una nuova raccolta

L'aumento graduale è particolarmente importante se esegui la migrazione del traffico delle app da una raccolta a un'altra. Un modo semplice per gestire questa migrazione è leggere dalla vecchia raccolta e, se il documento non esiste, leggere dalla nuova raccolta. Tuttavia, ciò potrebbe causare un improvviso aumento del traffico per chiudere lessicograficamente i documenti della nuova raccolta. Cloud Firestore potrebbe non essere in grado di preparare in modo efficiente la nuova raccolta per l'aumento del traffico, soprattutto quando contiene pochi documenti.

Un problema simile può verificarsi se si modificano gli ID documento di molti documenti all'interno della stessa raccolta.

La migliore strategia per la migrazione del traffico a una nuova raccolta dipende dal modello di dati. Di seguito è riportato un esempio di strategia nota come letture parallele . Dovrai determinare se questa strategia è efficace o meno per i tuoi dati e una considerazione importante sarà l'impatto sui costi delle operazioni parallele durante la migrazione.

Letture parallele

Per implementare letture parallele durante la migrazione del traffico a una nuova raccolta, leggi prima dalla vecchia raccolta. Se manca il documento, leggi dalla nuova raccolta. Un alto tasso di letture di documenti inesistenti può portare a hotspotting, quindi assicurati di aumentare gradualmente il carico della nuova raccolta. Una strategia migliore consiste nel copiare il vecchio documento nella nuova raccolta, quindi eliminare il vecchio documento. Aumenta gradualmente le letture parallele per assicurarti che Cloud Firestore sia in grado di gestire il traffico verso la nuova raccolta.

Una possibile strategia per aumentare gradualmente le letture o le scritture in una nuova raccolta consiste nell'usare un hash deterministico dell'ID utente per selezionare una percentuale casuale di utenti che tentano di scrivere nuovi documenti. Assicurati che il risultato dell'hash dell'ID utente non sia distorto dalla tua funzione o dal comportamento dell'utente.

Nel frattempo, esegui un lavoro batch che copia tutti i tuoi dati dai vecchi documenti alla nuova raccolta. Il tuo processo batch dovrebbe evitare le scritture su ID documento sequenziali per evitare hotspot. Al termine del processo batch, è possibile leggere solo dalla nuova raccolta.

Un perfezionamento di questa strategia consiste nel migrare piccoli batch di utenti alla volta. Aggiungi un campo al documento dell'utente che tenga traccia dello stato di migrazione di quell'utente. Seleziona un batch di utenti di cui eseguire la migrazione in base a un hash dell'ID utente. Utilizzare un processo batch per migrare i documenti per quel batch di utenti e utilizzare le letture parallele per gli utenti nel mezzo della migrazione.

Si noti che non è possibile eseguire facilmente il rollback a meno che non si eseguano doppie scritture sia della vecchia che della nuova entità durante la fase di migrazione. Ciò aumenterebbe i costi sostenuti per Cloud Firestore.

Impedire l'accesso non autorizzato

Impedisci le operazioni non autorizzate sul tuo database con le regole di sicurezza di Cloud Firestore. Ad esempio, l'utilizzo delle regole potrebbe evitare uno scenario in cui un utente malintenzionato scarica ripetutamente l'intero database.

Ulteriori informazioni sull'utilizzo delle regole di sicurezza di Cloud Firestore .