Alexandre Assis · Follow
Published in · 8 min read · Nov 27, 2019
--
Vai começar um sistema novo? Às vezes, com a urgência em colocar uma aplicação no ar, negligenciamos alguns pontos muito importantes. Mas, se tivermos tempo e disponibilidade na hora de definir e construir uma solução, podemos levar as melhores práticas como guia.
Recentemente realizei a palestra “Escalabilidade em Microsserviços” no Instituto Infnet. Um dos principais itens apresentados está relacionado ao planejamento para design de banco de dados. Por isso, achei relevante elencar neste artigo 6 práticas essenciais de #database que vão te ajudar muito no desenvolvimento de um novo sistema. Confira!
Se você tem tempo para planejar, considere tudo. Quais informações será preciso guardar? Quais tomadas de decisão serão necessárias? Como será modelado? Como defino o meu domínio? Então, você começa a planejar bem tudo isso para entender o que será válido para a aplicação ou não.
Por exemplo, você fez uma persistência de alguma lógica para uma loja e negligenciou os pontos de vista, fazendo sempre a consulta do produto pelo preço. Você definiu e assumiu isso, mas quando colocou o site no ar, percebeu que os usuários queriam buscar os produtos por um outro critério. Por exemplo: televisões que tenham determinado tamanho de tela. A partir disso, você passa a ter outros critérios na busca.
Ao não considerar este ponto durante o seu planejamento, muito provavelmente você terá de fazer alguma solução paliativa para criar uma consulta mega complexa. E essa consulta mega complexa vai ferir a sua base de dados. Por tanto, considere, pense, troque ideias com a equipe para prever possíveis pontos que irão impactar no banco futuramente.
Hoje, alguns bancos de dados estão na moda, como Cassandra e Mongo. Parece que hoje eles viraram “bala de prata” para resolver qualquer tipo de problema. Vão resolver? Não, não vão, porque depende da necessidade do sistema.
O mesmo banco de dados não vai servir para tudo o que você precisa. Por exemplo, se você utiliza uma chave natural que sabe que nunca vai mudar, como uma busca por CPF, opte por um NoSQL. No entanto, supondo que você precise fazer uma ferramenta de atendimento, como um call center por exemplo, em que você precisa ter várias consultas com várias visões do seu domínio, opte pelo relacional.
Performance em cima de uma chave que nunca vai mudar ➡ NoSQL
Vários tipos de consultas a serem empregadas em cima do modelo ➡ Relacional
Normalizar não relacional? Sim, também!
Parece um pouco contraditório, mas, por exemplo, imagine que você tem duas entidades: cliente e produto, em que a chave do seu cliente é o CPF e a chave do produto é um código de identificação. Daí, a partir disso, você gostaria de representar uma venda: produtos foram vendidos pelo site X para o cliente Y.
Já vi casos de desenvolvedores utilizarem a entidade do documento de produto referenciando os usuários que compraram. Também já vi casos onde fizeram o oposto. Colocaram referência de produtos dentro da tabela de documentos de usuários.
Então, o que acontece quando for necessário buscar todos os produtos que foram vendidos? Será necessário navegar em cima da entidade de produtos para saber quem foram os usuários que compraram. Isso não é escalável e não performa bem.
De repente, uma outra visão pode ser muito melhor: se possuo os dados cliente e produto, por que não criar uma outra entidade de documento denominada: “venda”?
Quando este documento for gerado, é possível inserir a identificação que referencia o produto e a identificação que referencia o cliente.
Agora fica mais fácil tendo uma entidade única, buscar a informação que se precisa.
Sempre evite jogar coisas dentro de documentos que vão complicar uma consulta futura.
Algumas vezes, acabamos persistindo muita informação desnecessária em nosso banco de dados. Por exemplo, para a validação de uma regra de negócio ou apenas para um enriquecimento de dados, pode estar em sobrecarga apenas pelo fato de estar trazendo informação demais para o seu contexto.
Na maioria das vezes, um grande volume de informações passa pelo nosso fluxo de negócios. Por exemplo, você faz uma consulta no Serasa e obtém uma resposta com uma série de informações do usuário. Pode vir o nome, nome da mãe, endereço, estado civil, idade, se declarou imposto de renda, se tem protesto e por aí vai. Então você persiste tudo no banco. Na hora de tomar a decisão e fazer uma consulta, de repente, todo esse overhead de informação vai trazer um peso que vai degradar a consulta no final, sendo que você só precisaria da informação de que ele estaria com o nome sujo naquele período em que a consulta aconteceu. Uma abordagem mais interessante poderia ser guardar no banco de dados apenas a data em que foi consultado e um booleano dizendo se o cliente está com o nome limpo ou sujo.
Se entendemos que as informações podem ser relevantes para uma análise futura, registramos em arquivos de log num formato bem estruturado. Pode ser em formato JSON ou PARQUET. Assim, podemos ter processos de ETL que consolidam esses dados numa estrutura para que os cientistas de dados possam efetuar suas análises.
Sendo redundante, mas muito importante lembrar que somente sejam carregadas as informações necessárias para o contexto da aplicação/serviço. Todo o resto dos dados, jogue em Logs estruturados para serem analisadas posteriormente.
Se você puder, logo no início da sua solução, trabalhando com banco relacional ou não relacional, considere o particionamento de data.
Por exemplo: Você tem uma tabela no banco de dados chamada CLIENTES. Isso quer dizer que o sistema gerenciado de banco de dados criou um arquivo em disco para armazenar os registros desta tabela. Então, você começa a inserir os registros de clientes. Ao longo do tempo, você percebe que sua tabela contém milhões de registros e que suas consultas estão cada vez mais lentas. Isso acontece porque todos os dados da tabela estão em um arquivo só e este está ficando gigante e computacionalmente falando, é muito custoso varrer arquivos em disco.
A primeira coisa que todo mundo faz para resolver este problema é criar os índices. De fato, eles costumam resolver. Mas também podem gerar outros problemas. Se você muitos critérios variados de busca, precisará criar índices para cada um deles. Porém, note que para cada índice que você cria, o sistema de banco pode criar uma estrutura de recuperação que pode ocupar até mais do tamanho do arquivo em disco do que sua tabela física. Então, pode ser que aumente muito seu custo de infra para suportar a quantidade de índices necessários para atender suas múltiplas visões.
Então, agora que você tem um índice e faz a consulta, o resultado vai surgir rapidamente. Mas aí você tem de pesquisar em cima de algo que não está indexado, o que vai acontecer? Uma busca extremamente longa em um arquivo de, por exemplo, 30TB. Linha por linha… Horas e horas esperando o retorno… Aplicação travada.. Clientes reclamando.. E por aí vai…
Nessa hora você pensa: “Nossa, por que eu não particionei esses dados?”
Como fazer isso?
Vou usar um exemplo de um problema que tivemos, no mercado telecom. Separamos os números de telefones dos usuários por DDD. O banco gera um um arquivo diferente para cada localidade, pois quando precisar realizar uma busca, não vai ter que varrer um documento gigantesco em que todas as informações estão misturadas e acredite, a segmentação da informação vai facilitar muito o trabalho.
Temos cenários em que particionamos por data também. A partir disso, fica mais simples até na hora do expurgo. Pense só, sem a partição, como o banco de dados faz para remover registros da tabela de um determinado período? Se tudo está misturado, ele vai precisar lockar a tabela. Isso já pode trazer um grande transtorno para sua aplicação, que vai ficar esperando esse processo terminar. Com a tabela particionada, o banco não precisa nem pensar. Consegue remover milhões de registros em segundos apenas deletando o arquivo que referencia aquela tabela através do seu particionamento lógico.
Faz sentido você manter a informação de uma venda que foi feita há mais de cinco anos? Se não fizer, expurgue-a. Ou a jogue para um arquivo morto. Qualquer que seja a sua escolha, não deixe essa informação defasada no banco de dados, pois ela vai onerar a sua infraestrutura.
Essas são algumas boas práticas para planejamento de banco de dados que podem poupar muitas dores de cabeça no futuro. Tem mais alguma dica ou sugestão? Comente abaixo!
Alexandre Assis é Líder Técnico na Akross, spin-off da Mobicare, Arquiteto de Soluções com mais de 15 anos de experiência em sistemas de alta performance com alta disponibilidade. Oracle certified master java ee enterprise architect.
A Mobicare e a Akross combinam os Melhores Talentos, Tecnologias de Ponta, Práticas Agile e DevOps com Capacidades Operacionais avançadas para ajudar Operadoras Telecom e grandes empresas a gerarem novas receitas e a melhorarem a experiência dos seus próprios clientes.
Se você gosta de inovar, trabalhar com tecnologia de ponta e está sempre buscando conhecimento, somos um match perfeito!