NoSQL ou SQL? Quando uso um, outro ou ambos

Bancos de dados NoSQL

Na minha opinião o grande ganho que tivemos com o NoSQL foi o de nos acordar para o fato de que estávamos usando bancos de dados relacionais como a única opção para qualquer problema. Da até para parafrasear um famoso ditado:

“Dê para um desenvolvedor um banco de dados relacional e o mundo se torna um conjunto de tabelas”

Logotipo cretino

O interessante é que foi criado tanto hype em cima destes bancos de dados que estes em diversas situações passaram de solução a problema por serem mal aplicados. Sobre a origem do hype já falei a respeito alguns posts atrás: é o desconhecimento do conceito de valor. Talvez seja até mesmo um sentimento pueril, a paixão por estar lidando com algo novo, o que fica bem claro quando topamos com o “logotipo padrão” do “movimento”: a sigla SQL riscada, uma das metáforas mais tolas que já vi.

Neste post meu objetivo é expor quais os critérios que uso na adoção de um banco de dados, indiferente do fato deste ser relacional ou não.

Definição rápida: o que vêm a ser NoSQL?

Simples: qualquer banco de dados que não adote o paradigma relacional. Levando ao extremo o conceito, uma API que trabalhe com arquivos textuais poderia ser considerada um banco de dados NoSQL.  O termo possuí duas conotações, uma inteligente e outra nem tanto, respectivamente not only SQL e no SQL.

A grosso modo vejo três grandes categorias: documentais, baseados em grafos e chave/valor. São as categorias com as quais tenho alguma experiência e que tratarei neste post.

Breve descrição de cada categoria de banco de dados

(Como o modelo relacional já é velho conhecido da esmagadora maioria dos programadores vou me dedicar aqui apenas às categorias NoSQL)

Documental

Talvez seja a categoria mais popular dos bancos de dados NoSQL. Se caracteriza pelo fato de não termos tabelas com um número fixo de campos bem definidos, mas sim coleções. Cada coleção pode armazenar um ou mais documentos (no lugar de registros em uma tabela). A grosso modo um documento é apenas um agregado de atributos que não possui uma regra rígida que definda quais os tipos de cada atributo e qual tipo cada um deve possuir (são sem esquema, schemaless). Normalmente os documentos são salvos num formato similar ao JSON, tal como pode ser visto no exemplo abaixo:


// Um documento usado para representar uma pessoa
{nome: "Henrique", sobrenome:"Lobo Weissmann", apelido:"Kico", cidade:"Belo Horizonte"}
// Um outro documenot para representar uma pessoa na mesma coleção
{nome: "Maria Angélica", sobrenome:"Álvares da Silva e Silva", profissao:"Advogada", caes:['Zé','Fraude']}

Como pode ser visto no exemplo, eu posso ter registros bem diferentes um do outro dentro de uma mesma coleção. Soa estranho em um primeiro momento este tipo de abordagem, mas no modelo relacional a usamos de forma ineficiente o tempo inteiro sob a forma de tabelas esparsas. Uma tabela esparsa é aquela na qual vêmos uma multidão de colunas das quais apenas algumas são sempre preenchidas, e as demais apenas raramente. Para ilustrar esta situação, dê uma olhada na imagem a seguir, que representa um cadastro de equipamentos e materiais usados em uma obra.

Nesta tabela podemos ver um uso ruim do modelo relacional. Repare que há colunas cujo valor raríssimas vezes é preenchido, tal como pode ser visto no exemplo das colunas Altura de elevação e Diâmetro. Ao incluir colunas raramente usadas em nossa tabela, estamos na realidade jogando fora espaço de armazenamento e reduzindo a performance do sistema como um todo. Isto sem mencionar que tratamos objetos completamente diferentes como se fossem iguais,  o que nem sempre é uma boa idéia. Podemos ver a seguir os mesmos dados sendo representados no modelo documental:

{codigo:1, tipo:"Britador", potencia:"300 cv", peso:"2000 kg", tag:"BR-121", motores:3}
{codigo:2, tipo:"Cimento"}
{codigo:3, tipo:"Rompedor de matacos", altura:"4 metros", peso:"300 kg", tag:"RM-11"}
{codigo:4, tipo:"Empilhadeira", potencia:"10 cv", peso:"400 kg"}
{codigo:5, tipo:"Transportador de correia", altura_elevacao:"2 m"}
{codigo:6, tipo:"Tubulação", diametro:"30 cm"}

Se em seu sistema há  tabelas esparsas, talvez seja um bom momento para que você avaliar um banco de dados documental. Aliás, eu já escrevi alguma coisa mais detalhada sobre este modelo neste blog, que você pode conferir neste link.

Bancos de dados que adotam este modelo: MongoDB, CouchDB.

Chave-valor

Trata-se da categoria mais simples e que talvez traga os maiores ganhos de performance quando bem aplicada. Neste modelo, toda consulta ao banco de dados é feita apenas através de uma chave, que pode ou não ter algum valor (de qualquer tipo) relacionado. É muito usado na implementação de caches de sistema ou acesso a informações que são alteradas em tempo real. De todos os modelos, é o que possuí tempo de pesquisa mais curto: basicamente é uma pesquisa baseada no hash da chave.

Em 2010 tive uma experiência muito bem sucedida com um banco de dados que usa esta abordagem, o Memcached, que você pode ver neste link. É um tipo de banco de dados muito usado também para substituir sistemas de mensageria como JMS, pois oferece um modelo mais simples de programação. No entanto, de todos os modelos é também o menos confiável sob o ponto de vista de persistência, pois são normalmente bancos desenvolvidos para armazenar informações em memória, com pouco foco na garantia de persistência (há excessões, mas leve isto como regra).

Bancos de dados que adotam este modelo: Berkeley DB, Memcached, Redis

Baseados em grafo

Talvez a menos popular das categorias, este modelo tem como foco o relacionamento entre os objetos. A metáfora neste caso é o grafo. Não temos mais coleções, apenas vértices representando os objetos de nosso sistema e arestas indicando o relacionamento entre estes. Normalmente cada vértice representa um agregado de atributos, muito similar ao modelo documental.

A pesquisa pode ser feita tanto por algum dos atributos dos vértices quanto pelos relacionamentos entre os mesmos. Neste tipo de banco de dados podemos fazer pesquisas do tipo “amigo do amigo”. A aplicação mais óbvia é a sua lista de contatos em uma rede social. Outro exemplo interessante poderia ser a representação de alguma estrutura do tipo causa/efeito, como uma fábrica, em que cada etapa de produção gera a entrada para uma ou mais etapas que precisem ser monitoradas.

É interessante observar que aqui estamos lidando com um tipo de banco de dados que permite a aplicação de um modelo navegacional entre os elementos persistidos. O desenvolvedor pode, se quiser, caminhar no grafo ao implementar algoritmos de busca em profundidade ou busca do menor caminho.

Dica: escrever consultas por relacionamentos nestes bancos pdoe ser um processo muito chato. Uma ferramenta que tornará sua vida mais fácil se chama Gremlin, que a grosso modo é usado para escrever consultas mais complexas de forma simples. Depois dê uma olhada neste link.

Bancos de dados que adotam este modelo: Neo4J, VertexDB

Ganho em escalabilidade

Esse é um ponto controverso para mim. Vejo muita gente usando bases de dados NoSQL apenas para obter escalabilidade. Normalmente esta é obtida porque estes bancos de dados não implementam 100% do ACID e portanto passam a possuir funcionamento mais simples. Nem sempre isto é verdade: no caso do Neo4J, por exemplo, temos uma base de dados que o implementa 100%. Um outro argumento a favor destes bancos de dados é o de que consomem menos memória e configurar um cluster é mais simples. Tá: pode até ser, mas na minha opinião são argumentos que não tocam o núcleo da questão.

De nada adianta eu ter um banco de dados super leve se a estrutura de dados usada para armazenamento não for compatível com a modelagem do meu sistema. Se eu tenho um sistema simples como um blog, por exemplo, que ganho eu teria em implementá-lo usando um banco de dados do tipo chave/valor, documental ou baseado em grafos? Provávelmente nenhum, e o tal ganho em performance por parte do banco de dados seria perdido no parseamento feito pela minha aplicação.

Quando opto por uma base NoSQL difícilmente escalabilidade é A razão. O que realmente importa é que o modelo de persistência seja próximo da modelagem do meu sistema e que, com isto, minhas consultas sejam mais fáceis de serem escritas e o mapeamento entre o que está no banco de dados e minhas classes seja mais fácil e rápido de ser implementado e executado. Yeap: é neste ponto que o NoSQL passa a agregar valor.

Com relação a ganho de escalabilidade real, na minha experiência o único caso em que vejo isto ocorrer de forma mais fácil é com o modelo chave/valor implementando alguma forma de cacheamento. Em segundo lugar viria o uso de uma base documental quando lido com tabelas esparsas. Infelizmente ainda não tive a oportunidade de trabalhar em um sistema gigantesco em que pudesse ver isto funcionando (mas a itexto se interessa por este tipo de trabalho, sendo assim, caso queira implementar algo assim, nos procure ok? :D ).

Dificuldades com NoSQL

Nem tudo é lindo no mundo NoSQL. Há alguns problemas que ainda hoje podem me fazer evitar o uso de uma destas bases de dados. O primeiro destes problemas é o fato de que o vendor lock-in é certo. Como não há um padrão (e também não faz sentido existir um) a migração de um banco de dados para outro dentro de uma mesma categoria pode se mostrar uma tarefa bem trabalhosa.

Outro problema é a ausência de ferramentas de alto nível como as que encontramos no modelo relacional. Na maior parte das vezes me vejo usando apenas a linha de comando para fazer tudo o que preciso. No caso dos bancos de dados baseados em grafos a coisa está começando a melhorar com projetos como Gephi, por exemplo, mas ainda falta muito para que tenhamos um nível de qualidade satisfatório.

A curva de aprendizado também pode ser um problema. Como cada banco de dados apresenta a sua própria linguagem de consulta e manipulação, o desenvolvedor precisará adicionar cada vez mais e mais linguagens no seu cinto de utilidades.

Critérios de escolha: quando uso um ou outro (brinde incluso)

Desenvolvi uma planilha que atualmente possuí 15 critérios que me ajudam na escolha do modelo e você pode acessá-la a hora que quiser, bastando para isto clicar neste link (este é o brinde). O principal critério diz respeito à conformidade da minha modelagem com os modelos que conheço (incluindo o relacional). Caso o relacional se mostre o mais apto, sem sombra de dúvidas é o que irei adotar, deixando de lado os demais. Na maior parte das vezes, pelo menos o chave/valor é usado para otimizar uma ou outra parte dos meus sistemas.

É interessante observar que em 100% dos casos o modelo relacional sempre está presente. A razão para isto é muito simples: é o que atende ao maior número de casos e até hoje sempre me atendeu com excessão das situações que citei na breve descrição das categorias de bancos de dados que fiz acima. Ai que entra um detalhe muito importante pra mim:

Na prática os bancos de dados NoSQL complementam e não substituem o modelo relacional em minha experiência.

Caro Hypista, me desculpe jogar este banho de água fria em sua empolgação, mas a verdade para mim até este momento tem sido esta. Minhas tabelas relacionadas querendo ou não ainda atendem muito bem a esmagadora maioria das minhas necessidades enquanto arquiteto/desenvolvedor.

Concluindo

As bases de dados NoSQL são um excelente complemento para o modelo relacional, evitando que o apliquemos em situações para as quais não foi desenvolvido. A escolha por um modelo não relacional deve estar diretamente relacionada à compatibilidade da sua modelagem com uma ou outra categoria mais do que o mero ganho de performance.

Link para a planilha de critérios de seleção do modelo de banco de dados.

41 thoughts on “NoSQL ou SQL? Quando uso um, outro ou ambos

  1. Bem legal o post. Ultimamente tenho lido a respeito de NoSQL, mas até o momento estou focado apenas no modelo documental, especificamente no MongoDB.

  2. Olá Henrique,

    Muito bom o seu artigo. Concordo que existe um certo hype e tem muita gente entrando de cabeça sem entender onde está se metendo. Recentemente desenvolvi um projeto utilizando mongodb e estou bem satisfeito com o resultado até o momento. Ele é muito rápido e muito produtivo mesmo não tendo ferramentas de mercado (que eu conheça) como as que temos para oracle por exemplo. O fato de voce não estar preso a uma estrutura super rigida ajuda mas tentar aplicar o “pensamento relacional” nele pode tornar sua vida um inferno. O acesso ao banco na linguagem java só é interessante se você utilizar o spring data e querydsl http://www.querydsl.com/ . Ele funciona muito bem na amazon também. Se o projeto realmente necessitar vale a pena. Outro que pretendo olhar com calma é o Couchdb. É isso.

  3. Olá Leonardo, muito bom saber que você gostou, isto é muito importante para mim.
    Também tive algumas experiências bem bacanas com o MongoDB. Atualmente estou trabalhando mais com o Redis, com o qual estou fazendo algumas experiências muito interessantes que pretendo publicar neste blog em breve.

  4. Parabéns pelo excelente post, é difícil encontrar um blog com real qualidade no conteúdo e com analises interessantes.

    Gostaria de acrescentar que a jboss pensando no vendor lock in já iniciou um subprojeto do hibernate para abstrair a comunicação com os bancos não relacionais.

    Vale a pena dar uma olhada em Hibernate OMG http://www.hibernate.org/subprojects/ogm

    Está em beta ainda

  5. Oi Francisco, bacana que tenha gostado, valeu!
    Não conhecia este projeto da JBoss, vou dar uma olhada. Meu único receio deste tipo de iniciativa é que talvez nós estejamos massificando o que não deveria ser massificado. Me pergunto: será que o ganho das bases não sql não seria justamente o seu diferencial? Não sei a resposta.

  6. Opa , a idéia central é simplificar ainda mais o modelo de programação de NoSQL, seguindo um modelo de persistência popular entre os desenvolvedores Java, JPA.

    Mais detalhes do framework aqui http://www.infoq.com/br/news/2011/06/hibernate-omg

    Eu penso ser muito interessante ter um framework responsável pelas decisões de persistência, desde que sejam baseados em domínio.

    A abstração da camada de persistência de um aplicação multi-camadas é sempre interessante

  7. Excelente artigo, foi muito instrutivo! No entanto ainda tenho muita dificuldade de pensar fora do relacional. Vocë poderia dar exemplos reais de domínios que seriam melhor atendidos com bases NoSQL?

  8. Oi Marcos, no artigo eu dou dois: um sistema de controle de materiais e equipamenots em uma obra é um belo exemplo.
    Imagine-o como um controle de estoque no qual você gasta um bom tempo adicionando atributos que variam de item pra item de acordo com seu tipo: cimento, tijolo, britadeira, etc.
    Cada um tem o seu próprio conjunto de atributos: consequentemente, se fossemos usar uma tabela, teríamos uma tabela esparsa tal como descrevi acima.

    Outro bom exemplo é a rede social. Tente modelar relacionalmente os relacionamentos entre seus membros. Como você vai perceber, é bastante complicado, porque você vai ter de fazer inúmeras consultas pra descobrir coisas como “amigos dos amigos”, e por aí vai.

    São os casos que já trabalhei, aonde o modelo relacional não se encaixava mais.

  9. Muito interessante esse post!
    Realmente essa coisa de NoSQL, levantou uma poeira danada na comunidade de desenvolvedores e afins. Eu gosto muito da definição de Not only SQL, pois isso levanta a questão de que os bancos relacionais não são a única opção, como muitos desenvolvedores fazem, fechando os olhos para outras coisas e o escolhendo, quando na verdade pode existir algo muito melhor para o domínio do problema. No caso que você citou sobre o blog, porque eu preciso usar um relacional, sendo que eu poderia estar utilizando algo mais leve, mais compatível com o meu modelo, etc (isso é só um exemplo).
    Assim como você, não peno nos NoSQLs com um substituto exatamente (em alguns casos podem ser) mas sim como complementos, sei que existem aplicações que utilizam mais de um tipo de banco de dados para atingir algum requisito. Bom é isso aí. vlw

  10. Que bom que gostou Mayko, valeu!

    É, vejo por aí também: mais como um complemento do que como um substituto.

  11. Olá Kiko. Venho acompanhando suas matérias.
    Gostaria de saber, se agora, já passado quase 1 ano, você ainda
    pensa desta maneira ( artigo ). Se possivel um faça um novo artigo.

    Parabéns e obrigado pelos artigos.

  12. Oi Alexandre, valeu!

    Excelente pergunta por sinal. Na maior parte minha visão se encontra inalterada.
    A única coisa que acabou se radicalizando pra mim é a necessidade de soluções mistas: conforme o tempo passa quando você olha pro vendor lock-in e o alto custo dos serviços (uma hora de consultoria com um consultor da MongoDB por exemplo custa US$ 450,00) acredito que devemos sempre optar por mais de uma base de dados: cada uma para uma parte do sistema.

  13. O final do artigo foi sensacional, parabéns!

    Acredito que um caso de uso para usar os dois modelos seria um usuário cadastra um livro, e esse livro é composto por vários capítulos. Sendo mais específico:

    * Usuário -> Perfil Usuário – Aqui poderíamos usar o MySQL, onde um usuário tem relacionamento com o seu perfil (Ele faz um cadastro rápido no site contento informações básicas, em seguida completa o seu perfil).

    * Livro+Capítulo(s) – Aqui acredito que seria um caso ideal para o sistema Documental, onde cada livro contém diversos capítulos, de maneira indeterminada.

    Espero ter contribuído, essa foi uma forma de eu tentar entender como funcionaria os dois juntos.
    Abraços.

  14. Oi Marcio,

    acho que da pra melhorar um pouco mais este seu exemplo. Talvez o documental fosse bacana para armazenar apenas o conteúdo dos capítulos, e o relacional para definir os relacionamentos entre livro e capítulos.

    O que ocorre: dependendo do banco que você for usar, MongoDB, por exemplo, há um limite no tamanho máximo do documento. Se este for muito grande (acho que o limite é 16 Mb) já não da pra armazenar.

    Se fosse muito grande, aliás, acabaria voltando tudo pro relacional, pois você poderia colocar em um campo blob (ou clob) o conteúdo e otimizar as consultas com um índice, por exemplo.

  15. Olá, tudo bem?
    Eu estava dando uma olhada na planilha que vc disponibilizou e achei algo estranho. No quesito “O grafo de relacionamentos entre meus objetos é muito complexo? (no modelo relacional eu precisaria de vários joins)”, não estaria faltando um xis na coluna do Grafo não?

    Inté!

  16. Opa,

    é, aprontei das minhas ali. Corrigi. Valeu! :)

  17. Olá Kico,
    em primeiro lugar parabéns pelo seu artigo.
    Neste momento vou começar a desenvolver um projeto acerca de bases de dados NoSQL do tipo column-family que tem como objetivo comparar o Cassandra e HBase em termos práticos. Não sei bem ao certo como o fazer mas gostaria de recorrer a algum tipo de ambiente integrado como o talend para o fazer.
    Já fez algo deste género? Que artigos ou casos práticos me aconselha a seguir? Neste momento procuro uma base por onde começar…

  18. Oi Pedro, obrigado!

    no caso do Cassandra minha experiência é nula, então não poderia te ajudar. Os SGBDs com os quais mais trabalhei foram o MongoDB, Redis, Neo4J

  19. Excelente artigo! Obrigada por compartilhar seus conhecimentos !

  20. Na planilha não encontrei nada quanto a escalabilidade, uma aplicação que irá ter muitos clientes é melhor ser feita utilizando NoSQL invés de SQL pensando que ao fazer SELECT de determinado usuário entre milhões pode ficar demorada a consulta? Ou como isso é tratado no modelo relacional? Agradeço pelo artigo e compartilhamento sobre essa informação.

  21. Oi Giancarlo, obrigado!

    Não ha este requisito por que normalmente escalabilidade é um resultado obtido a partir da arquitetura geral do sistema e não do SGBD apenas.

    E dica: se lhe disserem o contrário, desconfie! :)

  22. Ótimo artigo. Muito objetivo.

    Duvida. :
    Em um sistema de busca (tipo site de veiculos com 1Gb de dados) no MySQL (por exemplo) eu teria, para tabela de veiculos , alguns indices que ajudariam a buscar carros da marca x do ano y e com …
    Este tipo de busca (em vários campos/atributos) em um banco nosql seria mais lento que o SQL (por não existir indices). Certo?

  23. Oi Richard, obrigado.

    As bases de dados NoSQL tem índices também. O MongoDB, por exemplo, se não me engano, tem inclusive índice para buscas textuais. Tem de avaliar o que cada solução te proporciona.

  24. Olá.

    Excelente post, muito esclarecedor.
    Eu estava a procura de uma resposta para a pergunta: Posso usar ambos os modelos Relacional e NoSql no mesmo sistema? E no final do seu post encontrei a resposta, sim.
    Estou montando um sistema que Cursos, e para um banco de dados relacional a base inflará demais, pois o armazenamento de cada Aula vinculada aos Alunos do Curso crescerá rapidamente. Nessa parte estava pensando em usar um NoSql, mas o resto do sistema (Cursos, Matérias, Alunos, Professores, Turmas) ficarem a cargo do banco de dados relacional.
    Você acredita que é uma ótima opção utilizar ambas as tecnologias nesta situação?

  25. Oi Leandro,

    na minha opinião, você *deve* usar NoSQL principalmente como um complemento ao relacional (ou o relacional como complemento do NoSQL?).

    O que o relacional não der conta, você manda pro nosql e tira com isto proveito dos dois mundos.

  26. Esta solução que você está mostrando é exatamente a que usamos no nosso projeto Formação itexto – http://formacao.itexto.com.br

    No caso, o NoSQL seria o S3 da AWS para armazenamento de conteúdo estático, o restante, fica no relacional mesmo.

    E, em uma ponta, há também um chave-valor (Redis), que serve para controle de IPs, por exemplo.

  27. Olá Kiko, excelente publicação!!

    Gostaria de tirar uma dúvida. Na sua planilha (brinde), quando o item “Espaço em disco é caro” for verdadeiro, eu entendi que o modelo relacional seria o menos recomendado tendo em vista as “colunas raramente usadas”. De acordo com seu texto, no modelo relacional “Ao incluir colunas raramente usadas em nossa tabela, estamos na realidade jogando fora espaço de armazenamento e reduzindo a performance do sistema como um todo.”
    Então a dúvida é se esse item citado da planilha não está de acordo com esse entendimento, ou se há algum erro de interpretação da minha parte.

    Um abraço

  28. Opa, obrigado!

    Este é um bom ponto. Na realidade vai depender do SGBD usado. Creio que devo retornar este ponto portanto. Há alguns SGBDs que otimizam colunas não usadas, então dependeria realmente do caso. Bela observação!

    Uma solução nosql, por exemplo, que consumia muito espaço era o MongoDB.

  29. Prezado Kico,

    Ótimo artigo!

    Estamos em 2017, quase 5 anos após seu artigo ser publicado.

    Com isso, seguem as dúvidas:

    1 – Surgiram novas categorias? O Cassandra, BigTables e o S3 pertencem a qual?
    2 – É correto dizer que a categoria documental dominou o mercado?
    3 – Há algum exemplo prático de uma aplicação NoSql trabalhando junto com uma aplicação SQL relacional? (a intenção é entender melhor onde começa uma, onde a outra entra em ação, e como as duas se integram)
    4 – Atualmente está se falando bastante em SPA (Single Page Application). Teria algum exemplo prático de um SPA com NoSql e SQL?

    abs!

    Rolemberg

  30. oi, obrigado!

    Cinco anos depois o que posso dizer é que vejo cada vez menos gente usando NoSQL. Não é engraçado?

  31. Nops,

    é como você alerta em diversas partes do seu blog: CUIDADO COM O HYPE…

    Mas, no meu caso, que pretendo mudar para Portugal, vejo que algumas companhias solicitam o NoSql.

    Acredito que atualmente há um balanceamento na questão do cache, de modo a reduzir o tráfego no banco de dados.

    Novamente, há algum projeto em que há um mix de SQL com No SQL?

  32. Oi Rolemberg,

    sim, há vários. Inclusive este mix de SQL com NoSQL, na minha opiniao, é o melhor possível.

  33. Eu estava justamente procurando por um artigo assim. Estava na dúvida por todo esse hype gerado sobre NoSql. Excelente artigo, muito esclarecedor!
    Muito obrigado!

  34. Olá!
    Darei uma palestra de NoSQL x Relacional e achei muito interessante sua planilha.

    Gostaria de saber se posso mostra-la e indicar seu blog para as pessoas baixarem?

    att.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.