Back-End

23 jun, 2017

Você nem sempre precisa de um banco de dados

Publicidade

À medida que começamos um novo projeto, rapidamente começamos a pensar sobre o tipo de banco de dados que vamos usar. Opções como Oracle, SqlServer, Mysql ou mesmo um banco de dados NoSql como Mongo ou Cassandra sempre aparecem como uma boa escolha.

No entanto, esses bancos de dados ocupam dezenas ou centenas de megabytes (gigas?) no disco, além do fato de outra instalação, implantação, suporte, mais custos do nosso tempo.

 

Vale a pena?

Durante a maior parte do tempo, nossos aplicativos estarão armazenando apenas uma pequena quantidade de dados. Mesmo milhares de usuários, clientes e produtos levariam apenas alguns megabytes de seu disco. Vale a pena instalar um banco de dados inteiro (em outro servidor) apenas para isso? E se você ainda não conhece o esquema, você acabará usando e você ainda precisa mudar as tabelas o tempo todo?

Estive pensando nisso por algum tempo e um dia eu encontrei este artigo de Rob Conery falando sobre listas persistidas por um armazenamento json, com toda a bondade, velocidade e simplicidade. Fiquei louco com isso e comecei a usar a biblioteca imediatamente em um pequeno projeto meu.

Eu realmente gostei do framework, mas muito rapidamente muita gente também embarcou nessa e a biblioteca perdeu sua simplicidade, estabilidade e você nunca poderia saber qual repositório ou nuget era o oficial. Já não está mais no Github 🙁

Biggy ficou muito grande, então criei o Mini-Bigg

Comecei do zero usando o mesmo conceito, mas adicionando muitos recursos e cuidando para não adicionar complexidade. O objetivo era adicionar um pacote Nuget ao seu projeto e começar a codificar. Simples, incrível, rápido!

 

Então, como isso funciona?

Crie seu projeto e instale o MiniBiggy usando Nuget:

Install-Package mini-biggy

Crie uma classe chamada Tweet.

public class Tweet {
    public int UserId {get;set;}
    public string Message {get;set;}
}

O código acima criará um arquivo chamado tweets.data com nossa lista de tweets serializada. Chame Save() ou SaveAsync() para persistir a lista.

var t = new Tweet();
var list = CreateList<Tweet>.SavingAt("tweets.data")
                            .UsingJsonSerializer()
                            .SavingWhenRequested();
list.Add(t);
await list.SaveAsync();

E está tudo pronto.

 

Carregando-os mais tarde

Toda vez que você cria uma lista de algum tipo, ele irá carregar todos os objetos salvos desse tipo:

var list = CreateList<Tweet>.SavingAt("tweets.data")
                            .UsingJsonSerializer()
                            .SavingWhenRequested();
var count = list.Count(); //equals 1

Bondade de Linq

Lembre-se: sua lista está totalmente na memória. Então, qualquer operador linq funcionará perfeitamente:

biggyList.Where(x => x.Username == "admin" && x.Message.ToLower().Contains("urgent"))
         .OrderBy(x => x.DateTime)
         .FirstOrDefault();

E é tão rápido! Encontrar algo em uma lista de 1.000.000 leva apenas alguns milissegundos. As listas em memória são incríveis!

 

Serializadores

Mini-biggy vem com 2 serializadores:

  • JsonSerializer

 

  • PrettyJsonSerializer (o json está recuado)

Você pode alterar esse comportamento toda vez que você carrega sua lista.

 

Modos de economia

Você pode seguir 3 estratégias para salvar sua lista usando mini-biggy:

 

Salvamento manual

A lista será salva somente quando Save() ou SaveAsync() for chamado. Este é o comportamento padrão.

var t = new Tweet();
var list = CreateList<Tweet>.SavingAt("tweets.data")
                            .UsingJsonSerializer()
                            .SavingWhenRequested();
list.Add(t);
list.Save();

Salvamento automático

A lista será salva em cada alteração: adicionar, excluir ou atualizar um item salva a lista. Você ainda pode chamar Save e SaveAsync se desejar.

var t = new Tweet();
var list = CreateList<Tweet>.SavingAt("tweets.data")
                            .UsingJsonSerializer()
                            .SavingWhenCollectionChanges();
list.Add(t); //list saved

Observe que pode levar algum tempo para salvar, especialmente nos loops (use AddRange quando estiver nos loops).

 

Salvando em Plano de Fundo

Isso é realmente útil se a sua lista muda muito, especialmente por aplicativos multithread (web). A lista será salva a cada X segundos, mas somente se for modificada. Você ainda pode chamar Save e SaveAsync se desejar.

var t = new Tweet();
var list = CreateList<Tweet>.SavingAt("tweets.data")
                            .UsingJsonSerializer()
                            .BackgroundSavingEverySecond();
//or ...
var list = CreateList<Tweet>.SavingAt("tweets.data")
                            .UsingJsonSerializer()
                            .BackgroundSavingEvery(TimeSpan.FromSeconds(5));
list.Add(t); //it will be saved on next loop, in a background thread

 

Aplicações Web

Os aplicativos da Web são aplicativos multithread por natureza e haverá muitas requisições tentando acessar nossa lista persistente ao mesmo tempo. Não se preocupe, a lista é thread-safe. Apenas certifique-se de registrá-la como um singleton no seu DI de escolha, use a estratégia de salvar em Plano de Fundo e está tudo pronto.

 

Desempenho

Eu fiz alguns testes de desempenho não-científicos rápidos e sujos apenas para ter uma ideia sobre o quão grande o MiniBiggy pode ficar.

Aqui está o resultado:

Número de itens Salvo Carregado Encontrado <3 Arquivo no disco Memória
1,000 0.120s 0.005s 0.001s 61kB 0.09MB
1,000,000 0.350s 0.335s 0.005s 6.54MB 9.91MB
10,000,000 3.248s 3.985s 0.039s 68.345MB 99.17MB

 

Como você pode ver, as coisas são muito rápidas até chegar a alguns milhões de registros.

 

O mini-biggy é para você?

Mini-biggy é uma excelente opção para armazenar seus dados de persistência se:

  • Você quer um jeito rápido e simples para armazenar seus objetos.

 

  • Você tem menos de alguns milhões de objetos (cuidado com dispositivos móveis)

 

  • Você quer suporte Linq completo

 

  • Seus objetos são serializados em json e você cuidará deles ao mudar seu modelo

 

Onde está o código fonte? Como posso ajudar?

Encontre mais sobre o projeto em https://github.com/mini-biggy/mini-biggy!

 

***

Artigo traduzido com autorização. Publicado originalmente em 

http://www.andrecarlucci.com/en/you-dont-always-need-a-database/