Prós e Contras: Quando você deve ou não usar o MongoDB.

Originally written for Percona Blog in August, 2021 – Pros and Cons: When You Should and Should Not Use MongoDB


Muitas vezes, vemos que o banco de dados principal é usado em conjunto com alguns serviços adicionais, como, por exemplo, para cache ou busca textual completa.

Outra abordagem arquitetural que utiliza múltiplos bancos de dados é o uso de microservices, onde cada microserviço possui seu próprio banco de dados, otimizado para as tarefas específicas daquele serviço. Por exemplo, você pode usar MySQL para o armazenamento principal, Redis e Memcache para caching, Elastic Search ou Sphinx nativo para busca. Também é possível integrar algo como o Kafka para transferir dados para um sistema de análise, que frequentemente era implementado com ferramentas como o Hadoop.

Quando falamos sobre o banco de dados principal, há duas opções principais. Podemos escolher bancos de dados relacionais com linguagem SQL ou optar por um banco de dados não relacional, escolhendo entre os diferentes tipos disponíveis.

Dentro dos modelos de dados NoSQL, existem várias opções. As mais comuns são bancos de dados de chave-valor, documentos ou orientados a colunas.

Exemplos desses modelos incluem Memcache, MongoDB e Cassandra, respectivamente.

Olhando para o DB-Engines Ranking, podemos observar que a popularidade dos bancos de dados de código aberto tem crescido ao longo dos anos, enquanto os bancos de dados comerciais enfrentam um declínio gradual:

O que é ainda mais interessante é que essa mesma tendência tem sido observada para diferentes tipos de bancos de dados: bancos de dados de código aberto são os mais populares em várias categorias, como bancos de dados orientados a colunas, séries temporais e armazenamento de documentos. As licenças comerciais predominam apenas em tecnologias mais clássicas, como bancos de dados relacionais, ou ainda mais antigas, como os bancos de dados multivalorados.

Na Percona, trabalhamos de perto com os bancos de dados open-source mais populares, tanto relacionais quanto não relacionais (MySQL, PostgreSQL e MongoDB), lidando com diversos clientes. Ajudamos nossos clientes a fazer escolhas e oferecemos as melhores recomendações para cada caso.

Com isso em mente, este artigo tem como objetivo apresentar cenários que valem a pena considerar antes de implementar o MongoDB, levando você a refletir sobre quando deve ou não utilizá-lo. Além disso, mesmo que você já tenha seu ambiente configurado, este artigo pode ser interessante, já que, durante a avaliação de um produto, alguns dos tópicos a seguir podem ter passado despercebidos

Índice

Aqui está uma lista de tópicos que serão abordados ao longo deste artigo:

  1. Experiência e preferências da equipe
  2. Abordagem de desenvolvimento e ciclo de vida do aplicativo
  3. Modelo de dados
  4. Transações e consistência (ACID)
  5. Escalabilidade
  6. Administração

1. Experiência e Preferências da Equipe

Antes de implementar o MongoDB, a coisa mais importante é levar em conta a experiência e as preferências da equipe.

Do ponto de vista do MongoDB, uma das vantagens é a flexibilidade oferecida pelo formato de documentos em JSON. Para algumas tarefas e desenvolvedores, isso é extremamente conveniente. No entanto, para outras equipes, pode ser um desafio, especialmente se elas estão acostumadas a trabalhar com bancos de dados SQL há muito tempo e têm um bom domínio da linguagem SQL.

No MongoDB, é possível se familiarizar facilmente com as operações CRUD, como:

Consultas simples geralmente não causam problemas. Porém, assim que surge uma tarefa que exige um processamento de dados mais aprofundado, é essencial poder contar com uma ferramenta poderosa, como o  aggregation pipeline ou map-reduce, do MongoDB, que vamos abordar mais adiante neste artigo.

A MongoDB University oferece excelentes cursos gratuitos que podem ajudar muito na evolução do conhecimento da equipe. No entanto, é importante lembrar que alcançar o domínio completo pode levar tempo, especialmente se a equipe ainda não estiver totalmente familiarizada com a tecnologia.

2. Abordagem de Desenvolvimento e Ciclo de Vida do Aplicativo

Quando falamos de aplicativos que utilizam MongoDB, o foco geralmente está em um desenvolvimento rápido, pois é possível realizar mudanças a qualquer momento. Não é necessário se preocupar com um formato estrito para os documentos.

O segundo ponto é o esquema de dados(data schema). Aqui, é importante entender que os dados sempre possuem um esquema; a única questão é onde ele será implementado. Você pode implementar o esquema de dados no nível do aplicativo, já que, de alguma forma, ele reflete os dados que você utiliza. Ou, então, esse esquema pode ser implementado no nível do banco de dados.

É bastante comum que um aplicativo seja o único a lidar com os dados armazenados no banco. Por exemplo, se salvamos dados do aplicativo em um banco de dados, o esquema definido no nível do aplicativo funciona bem. Porém, se os mesmos dados forem usados por vários aplicativos, isso pode se tornar muito inconveniente e difícil de controlar.

Do ponto de vista do ciclo de desenvolvimento do aplicativo, isso pode ser representado da seguinte forma:

  • Rapidez no desenvolvimento
  • Nenhuma necessidade de sincronizar o esquema entre o banco de dados e o aplicativo
  • Facilidade para entender como escalar no futuro
  • Soluções simples e predefinidas

3. Modelo de Dados

Como mencionado no primeiro tópico, o modelo de dados é muito dependente da aplicação e da experiência da equipe.

Os dados de muitas aplicações web geralmente são fáceis de exibir. Isso porque, se armazenarmos a estrutura como um array da aplicação, é simples e claro para o desenvolvedor em um documento JSON.

Vamos a um exemplo. Queremos salvar uma lista de contatos de um telefone. Existem dados que se encaixam bem em uma tabela relacional: nome, sobrenome, etc. Mas, se olharmos para números de telefone ou endereços de e-mail, uma pessoa pode ter vários deles. Se quisermos armazenar isso em uma boa forma relacional, seria ideal colocá-los em tabelas separadas e depois coletá-los usando JOINs, o que é menos conveniente do que armazená-los em uma única coleção com documentos hierárquicos.

Modelo de Dados – Exemplo de Lista de Contatos

Banco de Dados Relacional

  • Nome, sobrenome, data de nascimento
  • Uma pessoa pode ter vários números de telefone e endereços de e-mail
  • É necessário criar tabelas separadas para armazenar esses dados
  • Arrays JSON são extensões não tradicionais

Banco de Dados Orientado a Documentos

  • Tudo é armazenado em um único documento.
  • Utiliza arrays e documentos embutidos.

No entanto, é crucial considerar que uma solução mais flexível pode resultar em uma lista de documentos com estruturas completamente diferentes. Como já disseram, “com grande poder vem grande responsabilidade.

Infelizmente, é bastante comum observar operações falhando ao gerenciar documentos maiores que 16MB ou coleções individuais contendo terabytes de dados. Pior ainda, em alguns casos, shard-keys mal projetadas podem agravar o problema.

Essas anomalias podem ser um forte indício de que você está transformando seu banco de dados em um Data Swamp. Esse é um termo comumente usado em implementações de Big Data para descrever dados mal projetados, inadequadamente documentados ou mal gerenciados.

Você não precisa normalizar seus dados de forma estrita, mas é essencial dedicar tempo para analisar como estruturar seus dados, a fim de aproveitar ao máximo o MongoDB e evitar esses problemas.

Você pode conferir o post no blog Schema Design in MongoDB vs Schema Design in MySQL para obter uma melhor entendimento sobre modelagem de dados e como ela difere entre as tecnologias. Vale destacar a funcionalidade de schema validation, que pode ser utilizada durante atualizações e inserções. É possível definir regras de validação em cada coleção, restringindo o tipo de conteúdo que será armazenado.

Termos

Curiosamente, ao modelar e consultar, há muitas semelhanças entre os SGBDs relacionais e não relacionais. Estamos falando de bancos de dados em ambos os casos, mas o que chamamos de tabela em um banco de dados relacional é frequentemente chamado de coleção em um banco de dados não relacional. O que é uma coluna no SQL, é um campo no MongoDB, e assim por diante.

Em relação ao uso de JOIN, que mencionamos anteriormente, o MongoDB não possui tal conceito diretamente. No entanto, é possível utilizar o operador $lookup dentro do aggregation pipeline. Ele realiza apenas um left outer join em sua busca. O uso excessivo de $lookup pode ser um indicativo de erros na modelagem de dados.

Quanto ao acesso: utilizamos SQL para dados relacionais. Para o MongoDB e muitos outros bancos de dados NoSQL, usamos um padrão como o CRUD. Esse padrão define operações para criar, ler, atualizar e excluir documentos.

Abaixo estão alguns exemplos das tarefas mais típicas para manipular documentos e seus equivalentes no mundo do SQL:

CREATE:

READ:

UPDATE:

DELETE:

Se você é um desenvolvedor familiarizado com a linguagem JavaScript, a sintaxe fornecida pelo MongoDB será mais natural para você do que a sintaxe do SQL.

Na minha opinião, quando lidamos com operações mais simples, como busca ou inserção, ambas as abordagens funcionam bem o suficiente. Porém, quando se trata de operações mais complexas, como a exemplificada acima, a linguagem SQL é muito mais legível.

COUNT:

É bastante fácil realizar tarefas como contar o número de linhas em uma tabela ou documentos em uma coleção.

Mas, se realizarmos tarefas mais complexas, como um GROUP BY no MongoDB, será necessário utilizar o Aggregation Framework. Uma interface mais avançada, que define como queremos filtrar, agrupar, entre outros aspectos.

Aggregation:

4. Transações e Consistência (ACID)

O motivo de abordar este tópico é que, dependendo dos requisitos do negócio, a solução de banco de dados pode precisar ser compatível com ACID. Nesse cenário, os bancos de dados relacionais estão muito à frente. Um excelente exemplo da necessidade de conformidade com ACID são operações envolvendo dinheiro.

Imagine que você está desenvolvendo uma função para transferir dinheiro de uma conta para outra. Se você debita o valor da conta de origem com sucesso, mas não credita na conta de destino; ou se, em vez disso, credita na conta de destino, mas não debita da conta de origem para cobrir o valor. Essas duas operações de escrita precisam acontecer juntas ou nenhuma delas pode ocorrer, mantendo o sistema consistente — o famoso “tudo ou nada”.

Antes do lançamento da versão 4.0, o MongoDB não suportava transações, mas oferecia suporte a operações atômicas dentro de um único documento.

Isso significa que, do ponto de vista de um único documento, a operação era atômica. No entanto, se o processo alterasse vários documentos e ocorresse alguma falha durante essas alterações, alguns documentos seriam modificados e outros, não.

Essa limitação foi removida a partir da versão 4.0 do MongoDB. Para situações que requerem atomicidade em leituras e escritas envolvendo múltiplos documentos (em uma ou várias coleções), o MongoDB passou a oferecer suporte a transações envolvendo múltiplos documentos. Isso pode ser aplicado em diversas operações, coleções, bancos de dados, documentos e até mesmo em shards, por meio de transações distribuídas.

  • Na versão 4.0, o MongoDB passou a suportar transações envolvendo múltiplos documentos em conjuntos de réplicas (replica sets).
  • Na versão 4.2, o MongoDB introduziu transações distribuídas, adicionando suporte para transações envolvendo múltiplos documentos em clusters shardeds e ampliando o suporte existente para conjuntos de réplicas.

5. Escalabilidade

O que é escalabilidade nesse contexto?

É a capacidade de transformar uma aplicação pequena em algo que suporte milhões ou até bilhões de usuários.

Se falarmos sobre a escalabilidade de um cluster onde nossas aplicações já são grandes o suficiente, fica claro que uma única máquina não será capaz de lidar com a carga, mesmo que seja a mais poderosa disponível.

Também faz sentido considerar se estamos escalando leituras, escritas ou o volume de dados. As prioridades podem variar entre diferentes aplicações, mas, em geral, aplicações muito grandes precisam lidar com todos esses aspectos.

No MongoDB, o foco inicial foi a escalabilidade entre múltiplos nós, mesmo para aplicações pequenas. Isso pode ser observado no recurso de Sharding, lançado desde seus primeiros dias de vida, que vem sendo continuamente desenvolvido e aprimorado desde então.

Se você procura por escalabilidade vertical, ela pode ser alcançada no MongoDB por meio da configuração de um Replica Set. Neste cenário e possível escalar sua base de dados para cima ou para baixo com poucos passos. Contudo, nesse caso, apenas a disponibilidade e as leituras são escaladas; as escritas ainda estão limitadas a um único ponto, o nó primário.

Sabemos, entretanto, que a aplicação eventualmente exigirá maior capacidade de escrita ou que o volume de dados se tornará grande demais para um Replica Set. Por isso, recomenda-se a escalabilidade horizontal utilizando o recurso de Sharding, que divide o conjunto de dados e distribui as escritas entre vários shards.

O Sharding no MongoDB apresenta algumas limitações: nem todas as operações são compatíveis com ele, tambem é importante destacar que um projeto ruim de chaves de shard(shard-keys) pode reduzir o desempenho das consultas, criar uma distribuição desigual dos dados e impactar as operações internas do cluster, como a divisão automática de dados. Em casos mais graves, isso pode exigir um re-sharding manual, uma operação extensa e propensa a erros.

Com o lançamento do MongoDB 5.0, foi introduzida a funcionalidade de resharding. Como acontece com qualquer novo recurso, minha recomendação é testá-lo extensivamente antes de utilizá-lo em produção. Se você estiver avaliando maneiras de refinar sua chave de shard e utilizar o re-sharding, o artigo “Refining Shard Keys in MongoDB 4.4 and Above” pode ser uma boa referência para fazer escolhas mais acertadas.

6. Administração

A administração inclui todas aquelas tarefas que os desenvolvedores geralmente não consideram, ou pelo menos não priorizam em primeiro lugar. Trata-se de aspectos como backup, atualização, monitoramento e restauração de uma aplicação em caso de falhas.

O MongoDB adota uma abordagem mais padronizada, onde a administração é minimizada. No entanto, isso ocorre à custa da flexibilidade. A comunidade open source de MongoDB é significativamente menor. Isso pode ser percebido no DB-Engines Ranking, mencionado no início deste artigo, e nas pesquisas anuais do StackOverflow. Sem dúvida, o MongoDB é o banco de dados NoSQL mais popular, mas carece de uma comunidade forte.

Além disso, muitas práticas recomendadas no MongoDB estão fortemente vinculadas aos serviços comerciais como Ops Manager e Atlas, ambos fornecidos pela MongoDB.

Até recentemente, executar rotinas de backup/restauração para um Sharded Cluster ou um Replica Set não era uma tarefa trivial. Os DBAs precisavam recorrer a métodos envolvendo a ferramenta mongodump/mongorestore ou ao uso de snapshots do sistema de arquivos.

Esse cenário começou a melhorar com recursos como o Percona Hot-Backup e a ferramenta Percona Backup for MongoDB.

Se compararmos com bancos de dados relacionais mais populares, como o MySQL, este se mostra mais flexível e oferece diversas abordagens. Existem implementações open source de alta qualidade para praticamente tudo, o que ainda é uma fraqueza existente no ecossistema do MongoDB.

Conclusão

Abordei alguns tópicos que podem ajudar na sua rotina, oferecendo uma visão ampla de onde o MongoDB pode trazer benefícios.

É importante considerar que este artigo foi escrito com base na versão mais recente disponível, o MongoDB 5.0. Se você já possui uma implementação usando versões mais antigas ou descontinuadas, algumas observações e funcionalidades mencionadas aqui podem não ser aplicáveis.

Se tiver dúvidas, sinta-se à vontade para deixá-las na seção de comentários abaixo.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *