Prácticas recomendadas
Usa las prácticas recomendadas que se indican aquí como referencia rápida cuando desarrolles una aplicación que use Firestore.
Ubicación de la base de datos
Cuando crees tu instancia de base de datos, selecciona la ubicación de la base de datos más cercana a tus 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 la durabilidad de tu aplicación, selecciona una ubicación multirregional y coloca los recursos de computación críticos en al menos dos regiones.
Selecciona una ubicación regional para reducir los costes o la latencia de escritura si tu aplicación es sensible a la latencia, o bien para colocarla junto con otros recursos de GCP.
IDs de documentos
- Evita los IDs de documento
.
y..
. - No uses
/
barras diagonales en los IDs de los documentos. No utilices IDs de documento que aumenten de forma monótona, como los siguientes:
Customer1
,Customer2
,Customer3
, ...Product 1
,Product 2
,Product 3
, ...
Estos IDs secuenciales pueden provocar puntos de acceso que afecten a la latencia.
Nombres de los campos
No uses los siguientes caracteres en los nombres de los campos, ya que requieren caracteres de escape adicionales:
.
punto[
corchete de apertura]
corchete de cierre*
asterisco`
acento grave
Índices
Reducir la latencia de escritura
El principal factor que influye en la latencia de escritura es la dispersión de índices. Las prácticas recomendadas para reducir la dispersión de índices son las siguientes:
Define exenciones de índice a nivel de colección. Una opción predeterminada sencilla es inhabilitar la indexación Descendente y de matriz. Si quita los valores indexados que no se usen, también se reducirán los costes de almacenamiento.
Reduce el número de documentos de una transacción. Si vas a escribir un gran número de documentos, te recomendamos que utilices un escritor en bloque en lugar del escritor de lote atómico.
Exenciones de índice
En la mayoría de las aplicaciones, puedes usar la indexación automática y los enlaces de los mensajes de error para gestionar los índices. Sin embargo, puede que quieras añadir exenciones de un solo campo en los siguientes casos:
Caso | Descripción |
---|---|
Campos de cadena grandes | Si tienes un campo de cadena que suele contener valores de cadena largos que no usas para las consultas, puedes reducir los costes de almacenamiento eximiendo el campo de la indexación. |
Velocidades de escritura altas en una colección que contiene documentos con valores secuenciales | Si indexas un campo que aumenta o disminuye de forma secuencial entre los documentos de una colección, como una marca de tiempo, la velocidad de escritura máxima en la colección será de 500 escrituras por segundo. Si no haces consultas basadas en el campo con valores secuenciales, puedes eximir el campo de la indexación para evitar este límite. En un caso práctico de IoT con una alta velocidad 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 usas políticas de tiempo de vida (TTL), ten 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 al rendimiento con tasas de tráfico más altas. Te recomendamos que añadas exenciones de un solo campo para tus campos TTL. |
Campos de matrices o mapas grandes | Los campos de matriz o de mapa grandes pueden acercarse al límite de 40.000 entradas de índice por documento. Si no vas a hacer consultas basadas en un campo de matriz o mapa grande, debes excluirlo de la indexación. |
Operaciones de lectura y escritura
La frecuencia máxima exacta con 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, consulta Actualizaciones de un solo documento.
Utiliza llamadas asíncronas en lugar de llamadas síncronas cuando estén disponibles. Las llamadas asíncronas minimizan el impacto de la latencia. Por ejemplo, supongamos que una aplicación necesita el resultado de una búsqueda de documentos y los resultados de una consulta antes de renderizar una respuesta. Si la búsqueda y la consulta no tienen una dependencia de datos, no es necesario esperar de forma síncrona a que se complete la búsqueda antes de iniciar la consulta.
No uses desplazamientos. En su lugar, usa cursores. Si usas un desplazamiento, solo evitarás que se devuelvan los documentos omitidos a tu aplicación, pero estos documentos se seguirán recuperando internamente. Los documentos omitidos afectan a la latencia de la consulta y se te factura por las operaciones de lectura necesarias para recuperarlos.
Reintentos de transacciones
Los SDKs y las bibliotecas de cliente de Firestore vuelven a intentar automáticamente las transacciones fallidas para hacer frente a los errores transitorios. Si tu aplicación accede a Firestore a través de las APIs REST o RPC directamente, en lugar de hacerlo a través de un SDK, debe implementar reintentos de transacciones para aumentar la fiabilidad.
Actualizaciones en tiempo real
Para conocer las prácticas recomendadas relacionadas con las actualizaciones en tiempo real, consulta Información sobre las consultas en tiempo real a gran escala.
Diseño para la escalabilidad
En las siguientes prácticas recomendadas se describe cómo evitar situaciones que provoquen problemas de contención.
Actualizaciones de un solo documento
Al diseñar tu aplicación, ten en cuenta la rapidez con la que actualiza documentos individuales. La mejor forma de caracterizar el rendimiento de tu 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. Entre los factores se incluyen la tasa de escritura, la contención entre solicitudes y el número de índices afectados.
Una operación de escritura de un documento actualiza el documento y los índices asociados, y Firestore aplica de forma síncrona la operación de escritura en un quórum de réplicas. Si las tasas de escritura son lo suficientemente altas, la base de datos empezará a tener problemas de contención, latencia más alta u otros errores.
Altas velocidades de lectura, escritura y eliminación en un intervalo de documentos reducido
Evita tasas de lectura o escritura altas en documentos cercanos lexicográficamente, ya que tu aplicación experimentará errores de contención. Este problema se conoce como "hotspotting" y tu aplicación puede sufrirlo si hace alguna de las siguientes acciones:
Crea documentos nuevos a una velocidad muy alta y asigna sus propios IDs, que aumentan de forma monótona.
Firestore asigna IDs de documento mediante un algoritmo de dispersión. No deberías tener problemas de puntos calientes en las escrituras si creas documentos con IDs de documento automáticos.
Crea documentos nuevos a un ritmo elevado en una colección con pocos documentos.
Crea documentos con un campo que aumenta de forma monótona, como una marca de tiempo, a un ritmo muy alto.
Elimina documentos de una colección a una velocidad alta.
Escribe en la base de datos a un ritmo muy alto sin aumentar el tráfico gradualmente.
Evitar saltarse los datos eliminados
Evita las consultas que omitan datos eliminados recientemente. Es posible que una consulta tenga que saltarse un gran número de entradas de índice si los resultados de la consulta inicial se han eliminado recientemente.
Un ejemplo de carga de trabajo que podría tener que saltarse una gran cantidad de datos eliminados es una que intente encontrar los elementos de trabajo en cola más antiguos. La consulta podría ser la siguiente:
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, se analizan las entradas de índice del campo created
de los documentos eliminados recientemente. Esto ralentiza las consultas.
Para mejorar el rendimiento, usa el método start_at
para encontrar el mejor lugar por el que 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: En el ejemplo anterior se usa un campo que aumenta de forma monótona, lo que no es recomendable para altas velocidades de escritura.
Aumentar el tráfico
Debes aumentar gradualmente el tráfico a las colecciones nuevas o a los documentos cercanos lexicográficamente para que Firestore tenga tiempo suficiente para preparar los documentos para el aumento del tráfico. Te recomendamos que empieces con un máximo de 500 operaciones por segundo en una colección nueva y, después, aumentes el tráfico en un 50 % cada 5 minutos. Puedes aumentar el tráfico de escritura de forma similar, pero ten en cuenta los límites estándar de Firestore. Asegúrate de que las operaciones se distribuyan de forma relativamente uniforme en todo el intervalo de claves. Esta es la regla "500/50/5".
Migrar tráfico a una colección nueva
El aumento gradual es especialmente importante si migras el tráfico de la aplicación de una colección a otra. Una forma sencilla de gestionar esta migración es leer de la colección antigua y, si el documento no existe, leer de la colección nueva. Sin embargo, esto podría provocar un aumento repentino del tráfico a los documentos cercanos lexicográficamente en la nueva colección. Es posible que Firestore no pueda preparar de forma eficiente la nueva colección para el aumento del tráfico, sobre todo si contiene pocos documentos.
Puede ocurrir un problema similar si cambia los IDs de documento de muchos documentos de la misma colección.
La mejor estrategia para migrar el tráfico a una nueva colección depende de tu modelo de datos. A continuación, se muestra un ejemplo de estrategia conocida como lecturas paralelas. Deberá determinar si esta estrategia es eficaz para sus datos. Un factor importante que debe tener en cuenta es el impacto en los costes de las operaciones paralelas durante la migración.
Lecturas paralelas
Para implementar lecturas paralelas mientras migras el tráfico a una colección nueva, lee primero de la colección antigua. Si falta el documento, lee de la nueva colección. Una tasa alta de lecturas de documentos inexistentes puede provocar un exceso de actividad, por lo que debes aumentar la carga gradualmente en la nueva colección. Una estrategia mejor es copiar el documento antiguo en la nueva colección y, a continuación, eliminar el documento antiguo. Aumenta las lecturas paralelas gradualmente para asegurarte de que Firestore pueda gestionar el tráfico a la nueva colección.
Una posible estrategia para aumentar gradualmente las lecturas o escrituras en una colección nueva es usar un hash determinista del ID de usuario para seleccionar un porcentaje aleatorio de usuarios que intenten escribir documentos nuevos. Asegúrate de que el resultado del hash del ID de usuario no se vea afectado por tu función ni por el comportamiento del usuario.
Mientras tanto, ejecuta un trabajo por lotes que copie todos tus datos de los documentos antiguos a la nueva colección. Tu trabajo por lotes debe evitar escribir en IDs de documento secuenciales para evitar puntos de acceso. Cuando finalice el trabajo por lotes, solo podrás leer de la nueva colección.
Una forma de mejorar esta estrategia es migrar pequeños grupos de usuarios a la vez. Añade un campo al documento de usuario que registre el estado de migración de ese usuario. Selecciona un lote de usuarios para migrarlo en función de un hash del ID de usuario. Usa una tarea por lotes para migrar los documentos de ese lote de usuarios y usa lecturas paralelas para los usuarios que estén a mitad de la migración.
Ten en cuenta que no podrás revertir fácilmente el proceso a menos que hagas escrituras duales de las entidades antiguas y nuevas durante la fase de migración. Esto aumentaría los costes de Firestore.
Privacidad
- No almacenes información sensible en un ID de proyecto de Cloud. Es posible que se conserve un ID de proyecto de Cloud más allá de la vida útil de tu proyecto.
- Como práctica recomendada para cumplir la normativa de datos, te aconsejamos que no almacenes información sensible en los nombres de los documentos ni en los nombres de los campos de los documentos.