Best practice per Cloud Firestore

Utilizza le best practice elencate qui come riferimento rapido quando si crea un'applicazione che utilizza Cloud Firestore.

Località del database

Quando crei la tua istanza di database, seleziona il campo database località più vicina a utenti e risorse di computing. Gli hop di rete ad ampio raggio sono più soggetti a errori e aumentano la latenza delle query.

Per massimizzare la disponibilità e la durabilità dei applicazione, seleziona una località con più regioni e collocare risorse di computing critiche in almeno due regioni.

Seleziona una località regionale per costi più bassi e una scrittura più bassa latenza, se la tua applicazione è sensibile alla latenza oppure per la colocation con altre risorse Google Cloud.

ID documento

  • Evita gli ID documento . e ...
  • Evita di utilizzare / barre negli ID documento.
  • Non utilizzare ID documento che aumentano in modo monotonico, ad esempio:

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

    Questi ID sequenziali possono generare hotspot che influiscono sulla latenza.

Nomi campi

  • Evita i seguenti caratteri nei nomi dei campi perché sono obbligatori escaping:

    • . punto
    • [ parentesi quadra aperta
    • ] parentesi quadra chiusa
    • * asterisco
    • Accento grave `

Indici

Riduci la latenza di scrittura

Il fattore principale che contribuisce alla latenza di scrittura è il fanout dell'indice. Le best practice per di riduzione del fanout dell'indice sono:

  • Imposta esenzioni degli indici a livello di raccolta. Un'impostazione predefinita semplice è disattivare l'ordinamento decrescente e l'indice array. La rimozione dei valori indicizzati inutilizzati ridurrà anche i costi di archiviazione.

  • Riduci il numero di documenti in una transazione. Per scrivere un numero elevato di documenti, valuta la possibilità di utilizzare uno scrittore collettivo anziché il batch atomico scrittore.

Esenzioni dell'indice

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

Richiesta Descrizione
Campi stringa grandi

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

Frequenze 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 per la raccolta è di 500 scritture al secondo. Se non esegui query basate sul campo con valori sequenziali, puoi escludere il campo dall'indicizzazione per aggirare questo limite.

In un caso d'uso IoT con un'elevata frequenza 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 di durata (TTL), tieni presente che il valore deve essere un timestamp. L'indicizzazione sui campi TTL è abilitata per impostazione predefinita e può influisce sulle prestazioni con tassi di traffico più elevati. Come best practice, aggiungi esenzioni a campo singolo per i campi TTL.

Array o campi mappa di grandi dimensioni

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

Operazioni di lettura e scrittura

  • La frequenza massima esatta con cui un'app può aggiornare un singolo documento dipende molto dal carico di lavoro. Per ulteriori informazioni, consulta Aggiornamenti a un singolo documento.

  • Utilizza chiamate asincrone, se disponibili, anziché chiamate sincrone. Le chiamate asincrone riducono al minimo l'impatto della latenza. Ad esempio, considera un'applicazione che ha bisogno del risultato di una ricerca di documenti e dei risultati di una query prima di visualizzare una risposta. Se la ricerca e la query non hanno una dipendenza dai dati, non è necessario attendere in modo sincrono il completamento della ricerca prima avviare la query.

  • Non utilizzare gli offset. Utilizza invece cursori. L'utilizzo di un offset evita solo restituendo all'applicazione i documenti ignorati, ma questi documenti sono recuperate internamente. I documenti ignorati influiscono sulla latenza e alla tua applicazione saranno addebitate le operazioni di lettura necessarie recuperarle.

Nuovi tentativi di transazione

Gli SDK e il client Cloud Firestore nuovo tentativo automatico delle librerie non riuscito le transazioni per gestire errori temporanei. Se la tua applicazione accede Cloud Firestore tramite REST o API RPC anziché tramite un SDK, l'applicazione deve implementare nuovi tentativi di transazione per aumentare l'affidabilità.

Aggiornamenti in tempo reale

Per le best practice relative agli aggiornamenti in tempo reale, consulta Comprendi le query in tempo reale su larga scala.

Progettazione per la scalabilità

Le seguenti best practice descrivono come evitare situazioni che creare contese.

Aggiornamenti a un singolo documento

Durante la progettazione dell'app, valuta la velocità con cui l'app aggiorna i singoli documenti. Il modo migliore per caratterizzare le prestazioni del carico di lavoro è eseguire il carico test. La frequenza massima esatta con cui un'app può aggiornare un singolo documento dipende molto dal carico di lavoro. I fattori includono la frequenza di scrittura, la concorrenza tra le richieste e il numero di indici interessati.

Un'operazione di scrittura del documento aggiorna il documento e gli eventuali indici associati, e Cloud Firestore applica in modo sincrono l'operazione di scrittura un quorum di repliche. Se le velocità di scrittura sono sufficientemente elevate, il database inizierà quando si verificano conflitti, latenza più elevata o altri errori.

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

Evita frequenze di lettura o scrittura elevate per chiudere i documenti in ordine alfabetico, altrimenti la tua applicazione riscontrerà errori di contesa. Questo problema è noto come hotspotting e la tua applicazione può rilevare l'hotspot se esegue una delle le seguenti:

  • Crea nuovi documenti a una frequenza elevata e assegna i propri ID monotonici crescenti.

    Cloud Firestore alloca gli ID documento utilizzando un algoritmo a dispersione. Tu non dovrebbero riscontrare hotspot sulle scritture se crei nuovi documenti utilizzando gli ID documento automatici.

  • Crea nuovi documenti ad alta velocità in una raccolta con pochi documenti.

  • Crea nuovi documenti con un campo in aumento monotono, ad esempio un timestamp, a una frequenza molto elevata.

  • Elimina i documenti di una raccolta ad alta frequenza.

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

Evita di saltare i dati eliminati

Evita le query che ignorano i dati eliminati di recente. Potrebbe essere necessario ignorare una query su un numero elevato di voci di indice se i risultati della query iniziale sono stati eliminati.

Un esempio di carico di lavoro che potrebbe dover saltare molti dati eliminati è una che tenta di trovare gli elementi di lavoro in coda più vecchi. La query potrebbe avere il seguente aspetto:

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, analizza le voci di indice alla ricerca Campo created in tutti i documenti eliminati di recente. Questo rallenta le query.

Per migliorare le prestazioni, utilizza il metodo start_at per trovare quella migliore punto di partenza. Ad 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 riportato sopra utilizza un campo che aumenta monotonicamente, che rappresenta un anti-pattern per alte velocità di scrittura.

Aumento del traffico

Devi aumentare gradualmente il traffico verso nuove raccolte o meno chiudi i documenti per concedere a Cloud Firestore il tempo sufficiente per prepararsi documenti per un aumento del traffico. Ti consigliamo di iniziare con un massimo di 500 operazioni al secondo a una nuova raccolta e quindi un aumento del traffico del 50% ogni 5 minuti. Analogamente, puoi aumentare il traffico di scrittura, ma tieni presente i limiti standard di Cloud Firestore. Assicurati che che le operazioni siano distribuite in modo relativamente uniforme nell'intervallo di chiavi. Questa è chiamata regola "500/50/5".

Migrazione del traffico a una nuova raccolta

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

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

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

Letture parallele

Per implementare letture parallele durante la migrazione del traffico a una nuova raccolta, leggi dalla vecchia raccolta. Se il documento non è presente, leggilo dal nuova raccolta. Un'elevata frequenza di lettura di documenti inesistenti può comportare hotspotting, quindi assicurati di aumentare gradualmente il carico sul nuovo . Una strategia migliore è copiare il vecchio documento nella nuova raccolta e poi eliminarlo. Incrementare gradualmente le letture parallele per garantire Cloud Firestore può gestire il traffico verso la nuova raccolta.

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

Nel frattempo, esegui un job batch che copia tutti i dati dai vecchi documenti la nuova raccolta. Il job batch deve evitare le scritture su documenti sequenziale ID per evitare gli hotspot. Al termine del job batch, della nuova raccolta.

Un perfezionamento di questa strategia consiste nella migrazione di piccoli gruppi di utenti alla volta. Aggiungi al documento dell'utente un campo che monitori lo stato della migrazione dell'utente. Seleziona un gruppo di utenti di cui eseguire la migrazione in base a un hash dell'ID utente. Utilizza le funzionalità di un job batch per eseguire la migrazione dei documenti per quel batch di utenti e letture parallele per gli utenti a metà della migrazione.

Tieni presente che non puoi eseguire facilmente il rollback a meno che non esegui scritture doppie sia delle entità vecchie che di quelle nuove durante la fase di migrazione. Questo aumenterebbe Cloud Firestore costi sostenuti.

Privacy

  • Evita di archiviare informazioni sensibili in un ID progetto Cloud. Un ID progetto Cloud potrebbe essere conservato oltre la durata del progetto.
  • Come best practice per la conformità dei dati, consigliamo di non archiviare dati informazioni nei nomi dei documenti e nei nomi dei campi dei documenti.

Impedire l'accesso non autorizzato

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

Scopri di più sull'utilizzo di Cloud Firestore Security Rules.