A Sardine usa o Google Cloud Datastore para alimentar parte da nossa interface de investigação. O Datastore é um banco de dados NoSQL gerenciado altamente escalável com uma interface flexível. O Datastore é muito importante para nossa infraestrutura, então estamos sempre buscando otimizá-lo.
À medida que escalamos, notamos que os custos do Datastore também aumentam substancialmente. Isso nos levou a nos aprofundar no entendimento dos tipos de custos associados ao Datastore e como poderíamos otimizar esses custos de olho no escalonamento futuro da nossa infraestrutura.
O Google também tem um produto chamado Firestore, que agora é posicionado como a próxima geração do Datastore. Quando começamos, o Firestore nativo ainda não estava em disponibilidade geral. Atualmente usamos o Firestore com compatibilidade com o Datastore.
Entendendo o preço do Datastore
Nosso primeiro passo nessa investigação foi entender o preço do Datastore. O Datastore cobra por:
- Solicitação de leitura
- Solicitação de escrita
- Solicitação de exclusão
- Armazenamento
Após a análise da equipe, determinamos que a maior parte do custo da Sardine vem do armazenamento de dados, principalmente porque temos muitos dados (e índices).
Entendendo a indexação do Datastore
Como o armazenamento (e a indexação) era onde precisávamos focar, quisemos entender o sistema de indexação do Datastore, já que isso nos ajudaria a otimizar os custos do Datastore.
Índices integrados
O Datastore é um armazenamento de documentos flexível (semelhante ao MongoDB), e por padrão, todas as colunas são indexadas. Isso significa que, se não tomarmos cuidado, acabaremos indexando muitos campos e aumentando nossos custos.
Índices compostos
Para suportar consultas com múltiplos filtros, precisamos adicionar índices compostos. O Datastore também requer índices para ordenação, então, para suportar a consulta a seguir, precisaremos de um índice composto de (customer_id, timestamp)
Os índices são ordenados; para suportar a ordenação timestamp DESC precisaremos de outro índice.
Analisando o uso de índices
O Google Cloud fornece diversos metadados para entender o uso de índices. Precisamos analisar tanto o uso de índices integrados quanto compostos para obter os dados de uso corretos.
Índices integrados
Para analisar o uso de índices integrados, a equipe executou a seguinte consulta:
Essa consulta revela estatísticas sobre cada índice integrado, incluindo:
- Tamanho do índice
- Última vez usado
- Última vez atualizado
Descobrimos que indexamos acidentalmente campos de lista para cada sessão, o que consumiu bastante espaço. E esses índices nem sequer eram usados.
Índices compostos
Para analisar os índices compostos, executamos a seguinte consulta:
Essa consulta revela estatísticas sobre cada índice integrado, incluindo:
- Tamanho do índice
- Última vez usado
- Última vez atualizado
Removendo índices
Agora que identificamos os índices custosos, a equipe pode começar o processo de removê-los. Para índices compostos, como os gerenciamos no terraform, é fácil removê-los. Índices integrados são mais complexos, porque são por objeto.
Quando nosso job de dataflow escreve dados no datastore, temos código como o seguinte:
O código não menciona nada sobre índices. No entanto, neste exemplo, o campo score está indexado, porque por padrão todos os campos são indexados.
Para evitar confusão, construímos uma função wrapper buildIndexedValue e buildUnindexedValue para que o código fique mais explícito, como no exemplo a seguir:
Além disso, tivemos que remover a indexação de campos de bilhões de registros existentes. Não há uma forma fácil de fazer isso, até onde sabemos. Então, escrevemos um script em python que lê os dados e os regrava com uma flag excludeFromIndex atualizada.
Conclusão
Os custos do Datastore muitas vezes crescem silenciosamente por causa de índices desnecessários. Ao fazer o seguinte, você pode obter economias notáveis de custo:
- Auditar as estatísticas de índices (
__Stat_Kind_BuiltinIndex__,__Stat_Kind_CompositeIndex__), - Remover os índices não utilizados.
- Marcar explicitamente os campos não consultáveis com
excludeFromIndexes=true.
Conte-nos o que você achou dessa abordagem. Não deixe de investigar sua solução de armazenamento de dados em busca de economias de custo e otimização!
Se você é alguém animado com a otimização do uso de nuvem, candidate-se aqui!

