Práticas recomendadas

Use as práticas recomendadas aqui como uma referência rápida ao criar um app que usa o Firestore.

Local do banco de dados

Ao criar uma instância de banco de dados, selecione o local do banco de dados mais próximo dos usuários e calcule os recursos. Os saltos de rede de longo alcance são mais propensos a erros e aumentam a latência das consultas.

Para maximizar a disponibilidade e a durabilidade do aplicativo, selecione um local de várias regiões e coloque recursos críticos de computação em pelo menos duas regiões.

Selecione um local regional para reduzir os custos, para diminuir a latência de gravação caso o aplicativo seja sensível à latência ou para compartilhar o local com outros recursos do GCP.

IDs de documentos;

  • Evite os IDs de documentos . e ...
  • Evite usar / (barras inclinadas) em IDs de documentos.
  • Não use IDs de documento que aumentam constantemente, como estes:

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

    Esses IDs sequenciais podem levar a pontos de acesso que afetam a latência.

Nomes dos campos

  • Evite os seguintes caracteres nos nomes de campos, porque eles exigem escape extra:

    • . (ponto)
    • [ (colchete esquerdo)
    • ] (colchete direito)
    • * (asterisco)
    • ` (acento grave)

Índices

  • Evite usar muitos índices. Um excesso de índices pode aumentar a latência de gravação e eleva os custos de armazenamento para entradas de índice.

  • Esteja ciente de que os campos de indexação com valores que crescem constantemente, como carimbo de data/hora, podem levar a pontos de acesso que afetam a latência de aplicativos com altas taxas de leitura e gravação.

Isenções de índice

Para a maioria dos aplicativos, é possível confiar na indexação automática, além de links de mensagens de erro para gerenciar seus índices. No entanto, é possível adicionar isenções de campo único nos seguintes casos:

Caso Descrição
Campos de string grandes

Se você tiver um campo de string que geralmente armazena valores de string longos que você não usa para consulta, é possível reduzir os custos de armazenamento com a isenção da indexação no campo.

Taxas de gravação altas em uma coleção que contém documentos com valores sequenciais

Se você indexar um campo que aumenta ou diminui sequencialmente entre documentos em uma coleção, como um carimbo de data/hora, a taxa máxima de gravação para a coleção será de 500 gravações por segundo. Se você não fizer consultas com base no campo com valores sequenciais, poderá isentar o campo da indexação para ignorar esse limite.

Em um caso de uso de Internet das Coisas (IoT, na sigla em inglês) com uma alta taxa de gravação, por exemplo, uma coleção que contém documentos com um campo de carimbo de data/hora pode se aproximar do limite de 500 gravações por segundo.

Campos grandes de matriz ou de mapa

Campos grandes de matriz ou de mapa podem se aproximar do limite de 40.000 entradas de índice por documento. Se você não estiver fazendo consultas com base em um campo grande de matriz ou de mapa, recomendamos isentá-lo da indexação.

Operações de leitura e gravação

  • Evite gravar em um documento mais de uma vez por segundo. Para mais informações, consulte Atualizações para um único documento.

  • Quando possível, use chamadas assíncronas, em vez de chamadas síncronas. As chamadas assíncronas reduzem o impacto da latência. Por exemplo, considere um aplicativo que precisa do resultado de uma pesquisa de documento e dos resultados de uma consulta antes de renderizar uma resposta. Se a pesquisa e a consulta não tiverem dependência de dados, não haverá necessidade de aguardar a conclusão da pesquisa de maneira síncrona antes de iniciar a consulta.

  • Não use deslocamentos. Em vez disso, use cursores. O uso de um deslocamento só evita o retorno dos documentos ignorados para o aplicativo, mas ainda é possível recuperar esses documentos internamente. Os documentos ignorados afetam a latência da consulta, e as operações de leitura necessárias para recuperá-los são cobradas do seu aplicativo.

Novas tentativas de transações

Os SDKs e as bibliotecas de clientes do Firestore repetem automaticamente as transações com falha para lidar com erros transitórios. Se o aplicativo acessar o Firestore por meio das APIs REST ou RPC diretamente, em vez de usar um SDK, o aplicativo deverá implementar novas tentativas de transação para aumentar a confiabilidade.

Atualizações em tempo real

Para alcançar o melhor desempenho de listeners de snapshots, mantenha seus documentos pequenos e controle a taxa de leitura dos seus clientes. As recomendações a seguir fornecem diretrizes para maximizar o desempenho. Exceder os valores indicados pode resultar no aumento da latência de notificações.

Recomendação Detalhes
Reduza a taxa de desligamento de usuários do listener de snapshots

Evite desligar os usuários dos listeners com frequência, especialmente quando o banco de dados estiver sob carga de gravação significativa

O ideal é que seu aplicativo configure todos os listeners de snapshots necessários logo após fazer uma conexão com o Firestore. Depois de configurar os listeners de snapshots iniciais, evite adicionar ou remover listeners na mesma conexão em um curto período.

Para garantir a consistência dos dados, o Firestore precisa preparar cada novo listener de snapshot a partir dos dados de origem e acompanhar as novas alterações. Dependendo da taxa de gravação do seu banco de dados, essa operação pode ser cara.

Os listeners de snapshots podem sofrer maior latência se forem adicionados ou removidos com frequência das referências. Em geral, para a mesma quantidade de dados, um listener constantemente conectado tem um desempenho melhor do que um que seja anexado e removido desse local. Para um melhor desempenho, os listeners de snapshot devem ter uma vida útil de 30 segundos ou mais. Se você encontrar problemas de desempenho do listener no aplicativo, tente acompanhar as detecções e as não detecções do aplicativo para determinar se elas podem estar acontecendo com muita frequência.

Restrinja os listeners de snapshots por cliente

100

Mantenha o número de listeners de snapshots por cliente abaixo de 100.

Restrinja a taxa de gravação da coleção

1.000 operações/segundo

Mantenha a taxa de operações de gravação para uma coleção individual abaixo de 1.000 operações/segundo.

Restrinja a taxa de push a clientes individualmente

1 documento/segundo

Mantenha a taxa de documentos que o banco de dados envia por push a um cliente individual abaixo de 1 documento/segundo.

Restrinja a taxa de push a clientes globalmente

1.000.000 documentos/segundo

Mantenha a taxa de documentos que o banco de dados envia por push a todos os clientes abaixo de 1.000.000 de documentos/segundo.

Restrinja o payload de documentos individualmente

10 KiB/segundo

Mantenha o tamanho máximo de documentos salvos por um cliente individual abaixo de 10 KiB/segundo.

Restrinja o payload de documentos globalmente

1 GiB/segundo

Mantenha o tamanho máximo de documentos salvos por todos os clientes abaixo de 1 GiB/segundo.

Restrinja o número de campos por documento

100

Seus documentos precisam ter menos de 100 campos.

Como entender os limites padrão do Firestore

Conheça os limites padrão do Firestore, principalmente o limite de 1 gravação/segundo para documentos e de 1.000.000 de conexões simultâneas por banco de dados.

Como desenvolver um design para escalonar

As práticas recomendadas a seguir descrevem como evitar situações que criam problemas de contenção:

Atualizações para um único documento

Evite atualizar um único documento mais de uma vez por segundo. Ao atualizar um documento muito rapidamente, seu aplicativo passará por contenções, inclusive aumento de latência, tempos limite excedidos e outros erros.

Altas taxas de leitura, gravação e exclusão para um intervalo de documentos estreito

Evite altas taxas de leitura ou gravação para fechar documentos lexicograficamente, ou seu aplicativo sofrerá erros de contenção. Esse problema é conhecido como uso excessivo do ponto de acesso, e seu aplicativo pode sofrer isso ao fazer o seguinte:

  • Criar novos documentos com uma taxa muito alta e alocar os próprios IDs constantemente crescentes.

    O Firestore aloca IDs de documentos usando um algoritmo de dispersão. Você não encontrará um uso excessivo do ponto de acesso em gravações se criar novos documentos ao usar IDs de documentos automáticos.

  • Criar novos documentos com uma alta taxa em uma coleção com poucos documentos.

  • Criar novos documentos com um campo constantemente crescente, como um carimbo de data/hora, com uma taxa muito alta.

  • Excluir documentos em uma coleção com uma taxa alta.

  • Gravar no banco de dados com uma taxa muito alta sem aumentar gradualmente o tráfego.

Como intensificar o tráfego

Intensifique gradualmente o tráfego para novas coleções ou documentos lexicograficamente próximos para que o Firestore tenha tempo suficiente de preparar os documentos para o aumento do tráfego. Recomendamos começar com um máximo de 500 operações por segundo para uma nova coleção e aumentar o tráfego em 50% a cada 5 minutos. Por exemplo, é possível usar essa programação de aumento para expandir seu tráfego de leitura para 740 mil operações por segundo após 90 minutos. Também é possível aumentar o tráfego de gravação, mas considere os limites padrão do Firestore. Confira se as operações estão distribuídas de forma relativamente uniforme por todo o intervalo de chaves. Isso é chamado de regra "500/50/5".

Como migrar o tráfego para uma nova coleção

O aumento gradual é particularmente importante quando você migra o tráfego de aplicativos de uma coleção para outra. Uma forma simples de lidar com essa migração é ler a coleção antiga e, se o documento não existir, ler a partir da nova coleção. No entanto, isso pode causar um aumento repentino de tráfego para fechar documentos lexicograficamente na nova coleção. O Firestore pode não conseguir preparar com eficiência a nova coleção para aumentar o tráfego, especialmente quando ela contém poucos documentos.

Um problema semelhante poderá ocorrer se você alterar os IDs de muitos documentos na mesma coleção.

A melhor estratégia para migrar o tráfego para uma nova coleção depende do seu modelo de dados. Veja a seguir uma estratégia de exemplo conhecida como leituras paralelas. É necessário determinar se essa estratégia é ou não eficaz para seus dados, e uma consideração importante é o impacto dos custos das operações paralelas durante a migração.

Leituras paralelas

Primeiro leia a coleção antiga para implementar leituras paralelas à medida que migrar o tráfego a uma nova coleção. Se não houver documento, leia a partir da nova coleção. Uma alta taxa de leitura de documentos inexistentes pode levar ao uso excessivo do ponto de acesso. Dessa forma, certifique-se de aumentar gradualmente a carga para a nova coleção. Uma melhor estratégia é copiar o documento antigo para a nova coleção e, em seguida, excluir o documento antigo. Aumente gradualmente a leitura paralela a fim de garantir que o Firestore possa lidar com o tráfego para a nova coleção.

Uma estratégia possível para aumentar gradualmente as leituras ou gravações em uma nova coleção é gerar um hash determinístico do ID do usuário para selecionar uma porcentagem aleatória de usuários que tentam gravar novos documentos. Verifique se o resultado do hash do código do usuário não foi distorcido pela função ou pelo comportamento do usuário.

Enquanto isso, gere um job em lote que copie todos os dados dos documentos antigos para a nova coleção. O trabalho em lote deve evitar gravações em IDs de documentos sequenciais para evitar pontos de acesso. Quando o trabalho em lote termina, é possível ler somente a partir da nova coleção.

Uma maneira de refinar essa estratégia é migrar lotes pequenos de usuários de uma só vez. Adicione um campo ao documento do usuário que rastreie o status de migração dele. Selecione um lote de usuários para migrar com base em um hash do ID do usuário. Use um job em lote para migrar documentos para esse lote de usuários e use leituras paralelas para os usuários no meio da migração.

Observe que a reversão não é fácil, a menos que você faça gravações duplas das entidades antigas e novas durante a fase de migração. Isso aumentaria os custos do Firestore.