Prácticas recomendadas para Cloud Firestore

Utilice las mejores prácticas que se enumeran aquí como referencia rápida al crear una aplicación que utilice Cloud Firestore.

Ubicación de la base de datos

Cuando cree su instancia de base de datos, seleccione la ubicación de la base de datos más cercana a sus usuarios y recursos informáticos. Los saltos de red de gran alcance son más propensos a errores y aumentan la latencia de las consultas.

Para maximizar la disponibilidad y durabilidad de su aplicación, seleccione una ubicación multirregional y coloque recursos informáticos críticos en al menos dos regiones.

Seleccione una ubicación regional para obtener costos más bajos, una latencia de escritura más baja si su aplicación es sensible a la latencia o para la ubicación conjunta con otros recursos de GCP .

ID de documentos

  • Evite los documentos de identidad . y .. .
  • Evite el uso / barras diagonales en los ID de los documentos.
  • No utilice ID de documentos que aumenten monótonamente, como:

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

    Estas identificaciones secuenciales pueden generar puntos de acceso que afecten la latencia.

Nombres de campo

  • Evite los siguientes caracteres en los nombres de los campos porque requieren escape adicional:

    • . período
    • [ corchete izquierdo
    • ] soporte derecho
    • * asterisco
    • ` comilla invertida

Índices

Reducir la latencia de escritura

El principal contribuyente a la latencia de escritura es el despliegue del índice. Las mejores prácticas para reducir el despliegue del índice son:

  • Establecer exenciones de índice a nivel de colección . Una opción predeterminada sencilla es desactivar la indexación descendente y de matriz. Eliminar los valores indexados no utilizados también reducirá los costos de almacenamiento .

  • Reducir la cantidad de documentos en una transacción. Para escribir una gran cantidad de documentos, considere utilizar un escritor masivo en lugar del escritor por lotes atómico.

Exenciones de índice

Para la mayoría de las aplicaciones, puede confiar en la indexación automática, así como en los enlaces de mensajes de error, para administrar sus índices. Sin embargo, es posible que desees agregar exenciones de un solo campo en los siguientes casos:

Caso Descripción
Campos de cadena grandes

Si tiene un campo de cadena que a menudo contiene valores de cadena largos que no utiliza para realizar consultas, puede reducir los costos de almacenamiento eximiendo el campo de la indexación.

Altas tasas de escritura en una colección que contiene documentos con valores secuenciales

Si indexa un campo que aumenta o disminuye secuencialmente entre documentos de una colección, como una marca de tiempo, entonces la velocidad máxima de escritura en la colección es de 500 escrituras por segundo. Si no realiza la consulta según el campo con valores secuenciales, puede eximir el campo de la indexación para evitar este límite.

En un caso de uso de IoT con una alta tasa de escritura, por ejemplo, una colección que contenga documentos con un campo de marca de tiempo podría acercarse al límite de 500 escrituras por segundo.

Campos TTL

Si utiliza políticas TTL (tiempo de vida) , tenga en cuenta que el campo TTL debe ser una marca de tiempo. La indexación en campos TTL está habilitada de forma predeterminada y puede afectar el rendimiento a tasas de tráfico más altas. Como práctica recomendada, agregue exenciones de campo único para sus campos TTL.

Grandes campos de matriz o mapa

Los campos grandes de matrices o mapas pueden acercarse al límite de 40.000 entradas de índice por documento. Si no realiza una consulta basada en una matriz grande o un campo de mapa, debe eximirlo de la indexación.

Operaciones de lectura y escritura.

  • La velocidad máxima exacta a la que una aplicación puede actualizar un solo documento depende en gran medida de la carga de trabajo. Para obtener más información, consulte Actualizaciones de un solo documento .

  • Utilice llamadas asincrónicas cuando estén disponibles en lugar de llamadas sincrónicas. Las llamadas asincrónicas minimizan el impacto de la latencia. Por ejemplo, considere una aplicación que necesita el resultado de una búsqueda de documentos y los resultados de una consulta antes de generar una respuesta. Si la búsqueda y la consulta no tienen una dependencia de datos, no es necesario esperar sincrónicamente hasta que se complete la búsqueda antes de iniciar la consulta.

  • No utilice compensaciones. En su lugar, utilice cursores . El uso de una compensación solo evita devolver los documentos omitidos a su aplicación, pero estos documentos aún se recuperan internamente. Los documentos omitidos afectan la latencia de la consulta y a su aplicación se le facturan las operaciones de lectura necesarias para recuperarlos.

Reintentos de transacciones

Los SDK de Cloud Firestore y las bibliotecas cliente reintentan automáticamente las transacciones fallidas para solucionar errores transitorios. Si su aplicación accede a Cloud Firestore a través de las API REST o RPC directamente en lugar de a través de un SDK, su aplicación debe implementar reintentos de transacciones para aumentar la confiabilidad.

Actualizaciones en tiempo real

Para conocer las mejores prácticas relacionadas con las actualizaciones en tiempo real, consulte Comprender las consultas en tiempo real a escala .

Diseñar a escala

Las siguientes mejores prácticas describen cómo evitar situaciones que creen problemas de discordia.

Actualizaciones en un solo documento

Al diseñar su aplicación, considere la rapidez con la que su aplicación actualiza documentos individuales. La mejor manera de caracterizar el rendimiento de su carga de trabajo es realizar pruebas de carga. La velocidad máxima exacta a la que una aplicación puede actualizar un solo documento depende en gran medida de la carga de trabajo. Los factores incluyen la velocidad de escritura, la contención entre solicitudes y el número de índices afectados.

Una operación de escritura de documento actualiza el documento y los índices asociados, y Cloud Firestore aplica sincrónicamente la operación de escritura en un quórum de réplicas. A velocidades de escritura suficientemente altas, la base de datos comenzará a encontrar contención, mayor latencia u otros errores.

Altas tasas de lectura, escritura y eliminación en un rango reducido de documentos

Evite altas tasas de lectura o escritura para cerrar documentos lexicográficamente, o su aplicación experimentará errores de contención. Este problema se conoce como hotspotting y su aplicación puede experimentar hotspotting si realiza alguna de las siguientes acciones:

  • Crea nuevos documentos a un ritmo muy alto y asigna sus propios ID que aumentan monótonamente.

    Cloud Firestore asigna ID de documentos mediante un algoritmo de dispersión. No debería encontrar puntos de acceso en las escrituras si crea nuevos documentos utilizando ID de documentos automáticos.

  • Crea nuevos documentos a un ritmo elevado en una colección con pocos documentos.

  • Crea nuevos documentos con un campo que aumenta monótonamente, como una marca de tiempo, a un ritmo muy alto.

  • Elimina documentos de una colección a un ritmo elevado.

  • Escribe en la base de datos a una velocidad muy alta sin aumentar gradualmente el tráfico.

Evite omitir datos eliminados

Evite consultas que omitan datos eliminados recientemente. Es posible que una consulta deba omitir una gran cantidad de entradas de índice si los primeros resultados de la consulta se eliminaron recientemente.

Un ejemplo de una carga de trabajo que podría tener que omitir una gran cantidad de datos eliminados es aquella que intenta encontrar los elementos de trabajo en cola más antiguos. La consulta podría verse así:

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()

Cada vez que se ejecuta esta consulta, escanea las entradas del índice en busca del campo created en cualquier documento eliminado recientemente. Esto ralentiza las consultas.

Para mejorar el rendimiento, utilice el método start_at para encontrar el mejor lugar para empezar. Por ejemplo:

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: El ejemplo anterior utiliza un campo que aumenta monótonamente, lo que es un antipatrón para altas velocidades de escritura.

Aumentar el tráfico

Debe aumentar gradualmente el tráfico hacia nuevas colecciones o cerrar documentos lexicográficamente para que Cloud Firestore tenga tiempo suficiente para preparar los documentos para un mayor tráfico. Recomendamos comenzar con un máximo de 500 operaciones por segundo para una nueva colección y luego aumentar el tráfico en un 50 % cada 5 minutos. De manera similar, puede aumentar su tráfico de escritura, pero tenga en cuenta los límites estándar de Cloud Firestore . Asegúrese de que las operaciones se distribuyan de manera relativamente uniforme en todo el rango de claves. Esto se llama la regla "500/50/5".

Migrar tráfico a una nueva colección

El aumento gradual es particularmente importante si migras el tráfico de aplicaciones de una colección a otra. Una forma sencilla de manejar esta migración es leer de la colección anterior y, si el documento no existe, leer de la nueva colección. Sin embargo, esto podría provocar un aumento repentino del tráfico para cerrar lexicográficamente documentos de la nueva colección. Es posible que Cloud Firestore no pueda preparar de manera eficiente la nueva colección para un mayor tráfico, especialmente cuando contiene pocos documentos.

Puede ocurrir un problema similar si cambia los ID de muchos documentos dentro de la misma colección.

La mejor estrategia para migrar el tráfico a una nueva colección depende de su modelo de datos. A continuación se muestra una estrategia de ejemplo conocida como lecturas paralelas . Deberá determinar si esta estrategia es efectiva o no para sus datos, y una consideración importante será el impacto en los costos de las operaciones paralelas durante la migración.

Lecturas paralelas

Para implementar lecturas paralelas al migrar tráfico a una nueva colección, lea primero la colección anterior. Si falta el documento, léalo de la nueva colección. Una alta tasa de lecturas de documentos inexistentes puede provocar puntos de acceso, así que asegúrese de aumentar gradualmente la carga de la nueva colección. Una mejor estrategia es copiar el documento antiguo a la nueva colección y luego eliminarlo. Aumente las lecturas paralelas gradualmente para garantizar que Cloud Firestore pueda manejar el tráfico a la nueva colección.

Una posible estrategia para aumentar gradualmente las lecturas o escrituras en una nueva colección es utilizar un hash determinista del ID de usuario para seleccionar un porcentaje aleatorio de usuarios que intentan escribir nuevos documentos. Asegúrese de que el resultado del hash de ID de usuario no esté sesgado ni por su función ni por el comportamiento del usuario.

Mientras tanto, ejecute un trabajo por lotes que copie todos los datos de los documentos antiguos a la nueva colección. Su trabajo por lotes debe evitar escrituras en ID de documentos secuenciales para evitar puntos de acceso. Cuando finalice el trabajo por lotes, solo podrá leer desde la nueva colección.

Una mejora de esta estrategia es migrar pequeños lotes de usuarios a la vez. Agregue un campo al documento de usuario que rastree el estado de migración de ese usuario. Seleccione un lote de usuarios para migrar según un hash del ID de usuario. Utilice un trabajo por lotes para migrar documentos para ese lote de usuarios y utilice lecturas paralelas para los usuarios en medio de la migración.

Tenga en cuenta que no puede revertir fácilmente a menos que realice escrituras duales de las entidades antiguas y nuevas durante la fase de migración. Esto aumentaría los costos incurridos en Cloud Firestore.

Privacidad

  • Evite almacenar información confidencial en un ID de proyecto en la nube. Es posible que se conserve un ID de proyecto en la nube más allá de la vida útil de su proyecto.
  • Como práctica recomendada de cumplimiento de datos, recomendamos no almacenar información confidencial en nombres de documentos y nombres de campos de documentos.

Evitar el acceso no autorizado

Evite operaciones no autorizadas en su base de datos con las reglas de seguridad de Cloud Firestore. Por ejemplo, el uso de reglas podría evitar un escenario en el que un usuario malintencionado descargue repetidamente toda su base de datos.

Obtenga más información sobre cómo usar las reglas de seguridad de Cloud Firestore .