sábado, 21 de setembro de 2013

The Little MongoDB Book - Capítulo 5 - Quando Usar MongoDB

Capítulo 5 - Quando Usar MongoDB

Até você deve ter uma idéia de onde e como ele pode se encaixar em seu sistema já existente.  Há muitas tecnologias novas de armazenamento competindo hoje em dia, o que torna fácil ficar em dúvida de qual escolher.
Para mim, o lição mais importante, que não tem nada a ver com MongoDB, é que você não tem que confiar em uma única solução para lidar com seus dados.  Sem dúvida, uma única solução tem vantagens óbvias, e para muitos projetos, é uma solução de abordagem mais sensata.  
A ideia não é que você deva usar diferentes tecnologias, mas sim saber que você pode fazer isso.  Só você sabe se os benefícios da introdução de uma nova solução superam os custos de sua implementação.
Estou esperançoso de que você tenha visto o MongoDB como uma solução geral.  Muitos comentam que banco de dados orientados a documentos possuem muito em comum com os bancos de dados relacionais.  Portanto, vamos simplesmente afirmar que MongoDB deve ser visto como uma alternativa direta as bases de dados relacionais.  Diferentemente de outros bancos NoSQL, como por exemplo, do Lucene que melhora um banco de dados relacional fazendo a indexação completa de texto, ou o Redis para armazenamento de chave-valor, o MongoDB é um repositório central de dados.
Repare que eu não chamei MongoDB de um substituto para banco de dados relacionais, mas sim uma alternativa.  É uma ferramenta que pode fazer o que o outras ferramentas também fazem.  Algumas delas, o MongoDB faz melhor, outras nem tanto.  Vamos falar mais disso adiante.

Sem Esquema (Schema-less)

Um benefício frequentemente elogiado de um banco de dados orientado a documentos é que eles são schema-less.  Isso os torna muito mais flexíveis do que as tabelas de banco de dados tradicionais.  Concordo que o schema-less é um bom recurso, mas não o principal que devemos mencionar.
As pessoas falam sobre schema-less como se você de repente fosse começar a armazenar dados misturando-os “loucamente”.  Existem domínios e conjuntos de dados que realmente pode ser doloroso modelá-los em um banco relacional, mas não vejo isso como um caso extremo.  Schema-less é legal, mas a maioria dos seus dados vão ser altamente estruturados.
É verdade que ocasionalmente isso pode ser útil, especialmente quando novas funcionalidades forem introduzidas, mas pensando bem, isso também poderia ser resolvido no relacional através de uma coluna que permita valor nulo.
Para mim, o benefício real do schema-less design é a falta de configuração e a redução do desacordo com a OOP.  Isto é particularmente verdade quando você está trabalhando com uma linguagem estática.  Eu já trabalhei com MongoDB em C3 e Ruby, e a diferença é gritante.
O dinamismo de Ruby e sua popular implementação do ActiveRecord já reduz muito a incompatibilidade com o objeto-relacional.  Isso não quer dizer que MongoDB não é bom para Ruby.  Pelo contrário, acho que a maioria dos desenvolvedores Ruby veria o MongoDB como uma melhoria, ao passo que os desenvolvedores C# ou Java iriam ver uma mudança fundamental na forma como eles interagem com seus dados.
Pense nisso a partir da perspectiva de um desenvolvedor de driver.  Você deseja salvar um objeto? Resposta: Serializar para JSON (tecnicamente BSON) e enviá-lo para o MongoDB.  Não há mapeamento de propriedade ou de tipo.  Esta simplicidade definitivamente flui para você, ou seja, para o desenvolvedor final.

Gravações

Uma área onde MongoDB esta se especializando é a de log.  Há dois aspectos do MongoDB que o faz ser rápido ao gravar dados.  Primeiro, você pode enviar um comando de escrita e não aguardar uma resposta do MongoDB.  Em segundo lugar, com a introdução do recurso jornaling na versão 1.8, e melhorias feitas na versão 2.0, você pode controlar o comportamento de escrita no que diz respeito a durabilidade dos dados.  
Essas configurações permitem especificar quantos servidores devem confirmar a gravação do dado antes de retornar para a aplicação.  Isso pode ser configurado para todas as gravações ou pontualmente em situações específicas.  Isso nos da um grande nível de controle sobre o desempenho de gravação e da durabilidade dos dados.
Além desses fatores de desempenho, log é um desses conjuntos de dados, que muitas vezes podem tirar proveito das coleções schema-less.
Por fim, MongoDB tem algo chamado capped collection. Até agora, todas as coleção criadas implicitamente são coleções normais.  Podemos criar uma coleção limitada usando o commando db.createCollection sinalizando-a como limitada.
// limita sua coleção em 1 megabyte
db.createCollection('logs', {capped: true, size: 1048576})

Quando a coleção limitada atinge seu limite de 1MB, documentos antigos são automaticamente removidos.  Um limite para o número de documentos, ao invés do tamanho, pode ser definido usando max. Coleções limitadas têm algumas propriedades interessantes.  Por exemplo, você pode atualizar um documento, mas ele não pode crescer em tamanho.  Além disso, a ordem de inserção é preservada, assim você não precisa adicionar um índice extra para obter a classificação com base no tempo adequado.
Ressalto que, se você quer saber se sua escrita encontrou erros (ao contrário do padrão fire-and-forget), você deve simplesmente executar o comando db.getLastError().  A maioria dos drivers encapsulam isso quando configurados para safe write, ou seja, especificando {:safe => true} como segundo parâmetro do insert.

Durabilidade

Antes da versão 1.8, MongoDB não possuía durabilidade em um único servidor.  Isto é, uma falha do servidor provavelmente resultaria em perda de dados.  A solução era sempre. Recorrer a uma configuração multi-servidor (replicação).  Um dos principais recursos adicionados a 1.8 foi o journaling.  
Para habilitá-lo, adicione a linha journal=true no arquivo de configuração mongodb.config que criamos quando configuramos o MongoDB pela primeira vez (reinicie o servidor se quiser que seja ativado imediatamente).  Isso é um tipo de configuração que você provavelmente que você sempre vai querer que esteja ativada (isso será um padrão nas próximas versões).  Apesar de em algumas circunstâncias a performance de ter o jornaling desativado ser maior, é um risco que você pode não estar disposto a correr.  
Durabilidade só é mencionada aqui, porque muita coisa já foi feita em torno da falta de durabilidade de um único servidor do MongoDB.  Isso provavelmente vai aparecer nas buscas do Google por algum tempo.  Se encontrar informações dizendo que é um recurso não existente no MongoDB, desconsidere, pois se trata de um informação desatualizada.

Pesquisa Completa de Texto (Full Text Search)

Esse é um recurso que esperamos que venha a existir nas próximas versões do MongoDB.  Com seu suporte às matrizes, implementar isso seria muito fácil.  Atualmente para isso, você precisará de uma solução como o Lucene/Solr.  Naturalmente, isto vale também para muitas bases de dados relacionais.

Transações

MongoDB não possui transações.  Ele tem duas alternativas, uma delas é muito boa, mas com uso limitado, e a outra seu uso é complicado, mas flexível.
A primeira consiste de suas operações atômicas.  São ótimas opções, desde que realmente resolvam o seu problema.  Nós já vimos algumas dessas operações mais simples como o $inc e o $set.  Há também comando como findAndModify  que pode atualizar ou excluir um documento e devolvê-lo atomicamente.
A segunda, quando as operações atômicas não são suficientes, é a volta para a two-phase commit (gravação de duas fases).    Two-phase commit são realmente muito populares no mundo relacional como forma de implementar transações entre vários bancos de dados. O site do MongoDB tem um exemplo que ilustra um cenário mais comum (transferência de fundos).  A idéia geral é que você armazene o estado da transação dentro do documento real que está sendo atualizado e através disso realizar os passos de init-pending-commit/rollback manualmente.

Processamento de Dados

A primeira consiste de suas operações atômicas.  São ótimas opções, desde que realmente resolvam o seu problema.  Nós já vimos algumas dessas operações mais simples como o $inc e o $set.  Há também comando como findAndModify  que podem atualizar ou excluir um documento e devolvê-lo atomicamente.
MongoDB depende de MapReduce para a maioria das tarefas de processamento de dados.  Ele até possui alguns recursos básicos de agregação, mas para algo sério, você vai precisar do MapReduce.  No próximo capítulo veremos MapReduce em detalhe.  Por hora, você pode pensar nele como sendo uma forma muito poderosa e diferente para realizar o group by.
Uma das forças do MapReduce é que ele pode ser paralelizado para trabalhar com grandes conjuntos de dados.  No entanto, a implementação do MongoDB depende de JavaScript, que é single-threaded.  Portanto, para o processamento de grandes volumes de dados, é provável que você precise de outra coisa, como o Hadoop.  Felizmente, os dois sistemas realmente se complementam mutuamente - há um MongoDB adapter for Hadoop.
Uma das forças do MapReduce é que ele pode ser paralelizado para trabalhar com grandes conjuntos de dados.  No entanto, a implementação do MongoDB depende de JavaScript, que é single-threaded.  Portanto, para o processamento de grandes volumes de dados, é provável que você precise de outra coisa, como o Hadoop.  Felizmente, os dois sistemas realmente se complementam mutuamente - há um MongoDB adapter for Hadoop.
É claro que paralelização de processamento de dados não é algo que banco de dados relacionais se destacam.  Existem planos para futuras versão do MongoDB no intuito de melhorar a forma de trabalhar com grandes conjuntos de dados.

Geospatial

Uma característica particularmente poderosa do MongoDB é seu suporte para índices geo-espaciais.  Isso permite que você armazene coordenadas x e y dentro de documentos e então realizar consulta através de $near que encontrará documentos próximos de uma determinada coordenada, ou através de $within que encontrará dentro de um quadrado ou círculo.

Ferramentas e Maturidade

Você provavelmente já sabe a resposta para isso, mas MongoDB é, obviamente, mais jovem do que a maioria dos sistemas de banco de dados relacionais.  Isto é absolutamente algo que você deve considerar, porém o quanto isso é importante vai depender do que e como você esta fazendo.
No entanto, em uma avaliação honesta, você simplesmente não pode ignorar o fato de que o MongoDB é mais jovem e que as ferramentas disponíveis ao redor não são tão boas (embora as ferramentas em torno de grande parte dos bancos de dados relacionais são horríveis demais!). Como exemplo, a falta de suporte para número base-10 de ponto flutuante é, obviamente, uma preocupação (embora não necessariamente seja um show-stopper) para sistema que lidam com dinheiro.
O lado positivo é que existem drivers para um grande número e linguagens.  O protocolo é moderno e simples e o desenvolvimento está acontecendo numa velocidade estonteante.  MongoDB está em produção em tantas empresas, que a preocupação inicial sobre sua validades, já é coisa do passado.

Neste Capítulo

A mensagem deste capítulo é que MongoDB, na maioria dos casos, pode substituir um banco de dados relacional.  É muito mais simples e direto, é mais rápido e, geralmente, impõe menos restrições sobre os desenvolvedores de aplicativo.

A falta de transações pode ser uma preocupação legítima e séria.  No entanto, quando as pessoas perguntam onde é que o MongoDB esta em relação ao novo cenário de armazenamento de dados, a resposta é simples: bem no meio.