Práticas recomendadas para o Cloud Firestore

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

Localização do banco de dados

Ao criar sua instância de banco de dados, selecione o local do banco de dados mais próximo dos usuários e dos recursos de cálculo. Saltos de rede de longo alcance são mais propensos a erros e aumentam a latência da consulta.

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

Selecione um local regional para reduzir custos, reduzir a latência de gravação se seu aplicativo for sensível à latência ou para colocalização com outros recursos do GCP .

IDs de documentos

  • Evite os IDs dos documentos . e .. .
  • Evite usar / barras em IDs de documentos.
  • Não use IDs de documentos que aumentam monotonicamente, como:

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

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

Nomes de campos

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

    • . período
    • [ colchete esquerdo
    • ] colchete direito
    • * asterisco
    • ` crase

Índices

Reduza a latência de gravação

O principal contribuinte para a latência de gravação é o fanout do índice. As melhores práticas para reduzir o fanout do índice são:

  • Defina isenções de índice em nível de coleção . Um padrão fácil é desabilitar a indexação descendente e de matriz. A remoção de valores indexados não utilizados também reduzirá os custos de armazenamento .

  • Reduza o número de documentos em uma transação. Para escrever um grande número de documentos, considere usar um gravador em massa em vez do gravador em lote atômico.

Isenções de índice

Para a maioria dos aplicativos, você pode contar com a indexação automática, bem como com links de mensagens de erro para gerenciar seus índices. No entanto, você pode querer 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 contém valores de string longos que não são usados ​​para consulta, você poderá reduzir os custos de armazenamento isentando o campo da indexação.

Altas taxas de gravação em uma coleção contendo 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 na coleção será de 500 gravações por segundo. Se você não fizer a consulta com base no campo com valores sequenciais, poderá isentar o campo da indexação para contornar esse limite.

Em um caso de uso de IoT com alta taxa de gravação, por exemplo, uma coleção contendo documentos com um campo de carimbo de data/hora pode se aproximar do limite de 500 gravações por segundo.

Campos TTL

Se você usar políticas TTL (time-to-live) , observe que o campo TTL deve ser um carimbo de data/hora. A indexação em campos TTL é habilitada por padrão e pode afetar o desempenho em taxas de tráfego mais altas. Como prática recomendada, adicione isenções de campo único para seus campos TTL.

Grande matriz ou campos de mapa

Grandes campos de array ou mapa podem atingir o limite de 40.000 entradas de índice por documento. Se você não estiver consultando com base em um array grande ou campo de mapa, deverá isentá-lo da indexação.

Operações de leitura e gravação

  • A taxa máxima exata que um aplicativo pode atualizar um único documento depende muito da carga de trabalho. Para obter mais informações, consulte Atualizações em um único documento .

  • Use chamadas assíncronas quando disponíveis, em vez de chamadas síncronas. As chamadas assíncronas minimizam 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 será necessário aguardar de forma síncrona até que a pesquisa seja concluída antes de iniciar a consulta.

  • Não use compensações. Em vez disso, use cursores . Usar um deslocamento evita apenas o retorno dos documentos ignorados ao seu aplicativo, mas esses documentos ainda são recuperados internamente. Os documentos ignorados afetam a latência da consulta e seu aplicativo é cobrado pelas operações de leitura necessárias para recuperá-los.

Novas tentativas de transações

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

Atualizações em tempo real

Para conhecer as práticas recomendadas relacionadas a atualizações em tempo real, consulte Compreender consultas em tempo real em escala .

Projetando para escala

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

Atualizações para um único documento

Ao projetar seu aplicativo, considere a rapidez com que ele atualiza documentos únicos. A melhor maneira de caracterizar o desempenho da sua carga de trabalho é realizar testes de carga. A taxa máxima exata que um aplicativo pode atualizar um único documento depende muito da carga de trabalho. Os fatores incluem a taxa de gravação, a contenção entre as solicitações e o número de índices afetados.

Uma operação de gravação de documento atualiza o documento e quaisquer índices associados, e o Cloud Firestore aplica a operação de gravação de forma síncrona em um quorum de réplicas. Em taxas de gravação suficientemente altas, o banco de dados começará a encontrar contenção, latência mais alta ou outros erros.

Altas taxas de leitura, gravação e exclusão em uma faixa restrita de documentos

Evite altas taxas de leitura ou gravação para fechar documentos lexicograficamente, ou seu aplicativo sofrerá erros de contenção. Esse problema é conhecido como hotspotting, e seu aplicativo pode sofrer hotspotting se executar qualquer um dos seguintes procedimentos:

  • Cria novos documentos em uma taxa muito alta e aloca seus próprios IDs que aumentam monotonicamente.

    O Cloud Firestore aloca IDs de documentos usando um algoritmo de dispersão. Você não deverá encontrar pontos de acesso em gravações se criar novos documentos usando IDs automáticos de documentos.

  • Cria novos documentos em alta velocidade em uma coleção com poucos documentos.

  • Cria novos documentos com um campo crescente monotonicamente, como um carimbo de data/hora, em uma taxa muito alta.

  • Exclui documentos de uma coleção com alta taxa.

  • Grava no banco de dados em uma taxa muito alta, sem aumentar gradualmente o tráfego.

Evite pular dados excluídos

Evite consultas que ignorem dados excluídos recentemente. Uma consulta poderá ter que ignorar um grande número de entradas de índice se os primeiros resultados da consulta tiverem sido excluídos recentemente.

Um exemplo de carga de trabalho que pode ter que ignorar muitos dados excluídos é aquela que tenta localizar os itens de trabalho mais antigos na fila. A consulta pode ser semelhante 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()

Cada vez que esta consulta é executada, ela verifica as entradas de índice do campo created em quaisquer documentos excluídos recentemente. Isso retarda as consultas.

Para melhorar o desempenho, use o método start_at para encontrar o melhor lugar para começar. Por exemplo:

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: O exemplo acima usa um campo crescente monotonicamente que é um antipadrão para altas taxas de gravação.

Aumentando o tráfego

Você deve aumentar gradualmente o tráfego para novas coleções ou fechar documentos lexicograficamente para dar ao Cloud Firestore tempo suficiente para preparar documentos para o aumento do tráfego. Recomendamos começar com no máximo 500 operações por segundo para uma nova coleta e depois aumentar o tráfego em 50% a cada 5 minutos. Da mesma forma, você pode aumentar seu tráfego de gravação, mas lembre-se dos limites padrão do Cloud Firestore . Certifique-se de que as operações sejam distribuídas de maneira relativamente uniforme em todo o intervalo de chaves. Isso é chamado de regra “500/50/5”.

Migrando tráfego para uma nova coleção

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

Um problema semelhante pode ocorrer se você alterar os IDs de vários documentos da mesma coleção.

A melhor estratégia para migrar o tráfego para uma nova coleção depende do seu modelo de dados. Abaixo está um exemplo de estratégia conhecida como leituras paralelas . Você precisará determinar se essa estratégia é ou não eficaz para seus dados, e uma consideração importante será o impacto nos custos das operações paralelas durante a migração.

Leituras paralelas

Para implementar leituras paralelas à medida que você migra o tráfego para uma nova coleção, leia primeiro a partir da coleção antiga. Se o documento estiver faltando, leia a nova coleção. Uma alta taxa de leituras de documentos inexistentes pode levar ao hotspotting, portanto, aumente gradualmente a carga para a nova coleção. Uma estratégia melhor é copiar o documento antigo para a nova coleção e depois excluir o documento antigo. Aumente as leituras paralelas gradualmente para garantir que o Cloud 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 é usar um hash determinístico do ID do usuário para selecionar uma porcentagem aleatória de usuários que tentam escrever novos documentos. Certifique-se de que o resultado do hash do ID do usuário não seja distorcido pela sua função ou pelo comportamento do usuário.

Enquanto isso, execute um trabalho em lote que copie todos os dados dos documentos antigos para a nova coleção. Seu trabalho em lote deve evitar gravações em IDs de documentos sequenciais para evitar pontos de acesso. Quando o trabalho em lote for concluído, você poderá ler somente a partir da nova coleção.

Um refinamento dessa estratégia é migrar pequenos lotes de usuários por vez. Adicione um campo ao documento do usuário que rastreia o status de migração desse usuário. Selecione um lote de usuários para migrar com base em um hash do ID do usuário. Use um trabalho em lote para migrar documentos desse lote de usuários e use leituras paralelas para usuários no meio da migração.

Observe que você não pode reverter facilmente, a menos que faça gravações duplas das entidades antigas e novas durante a fase de migração. Isso aumentaria os custos incorridos do Cloud Firestore.

Privacidade

  • Evite armazenar informações confidenciais em um ID de projeto do Cloud. Um ID do projeto do Cloud pode ser mantido além da vida útil do seu projeto.
  • Como prática recomendada de conformidade de dados, recomendamos não armazenar informações confidenciais em nomes de documentos e nomes de campos de documentos.

Impedir acesso não autorizado

Evite operações não autorizadas no seu banco de dados com as regras de segurança do Cloud Firestore. Por exemplo, o uso de regras pode evitar um cenário em que um usuário mal-intencionado baixe repetidamente todo o seu banco de dados.

Saiba mais sobre como usar as regras de segurança do Cloud Firestore .