Arquivo da tag: Oracle

Formatos dos Dados

Este assunto não é novidade, mas ainda é bastante incompreendido. Seja em um banco de dados, ou em arquivos (Big Data), podemos escolher basicamente dois tipos de formatos de dados: organizado por linhas, ou por colunas.

A organização por linhas é mais conhecida. Ela é principalmente utilizada em sistemas de informação transacionais: esses que as empresas usam no dia-a-dia. A orientação dos dados por linha é otimizada para esse tipo de sistema, porém, para ambientes analíticos, onde realizamos consultas com grandes agregações, esse formato não é realmente eficiente.

A organização dos dados por colunas é diametralmente o oposto: terrível para sistemas transacionais, e excelente para ambientes analíticos (data warehouse, data lakes e data lakehouses).

Neste post vou explicar por que e onde um tipo de formato é melhor que o outro.

Organização por Linha

Primeiro temos que entender quais são as características de um sistema transacional (OLTP) no contexto de um banco de dados.

Geralmente esses sistemas são caracterizados por requisições curtas, e com grande volume de acesso concorrente. Exemplos de requisições curtas:

  • Quais são os dados do cliente 1002;
  • Insira um produto novo na tabela;
  • Atualize a quantidade deste produto no estoque;
  • Me dê todas as informações do funcionário 8567.

Ou seja, requisições curtas são operações realizadas no banco de dados que envolvem um ou poucos registros por vez, seja para consulta, ou alteração, e em grande volume (muitos usuários concorrentes).

Outra característica importante é que praticamente todas as requisições nesse contexto utilizam (ou, deveriam utilizar) a chave primária (índice) da tabela, isto é, sempre estamos filtrando por um cliente, por um produto, por um funcionário…

Normalmente as tabelas em um sistema transacional são normalizadas (3FN), ou seja, os dados são espalhados em várias tabelas diferentes (conectados por chaves primárias e estrangeiras) por questões de integridade, e para evitar redundância de informação.

Dito isto, vamos para o formato de linha com um exemplo simples:

Nesta tabela temos 6 linhas, e 5 colunas, mas pense que em um banco de dados de verdade temos milhões ou bilhões de linhas. Fisicamente essas linhas são armazenadas, uma após a outra, em blocos, e cada bloco pode armazenar uma centena de linhas.

Neste exemplo, suponha que cada bloco consegue armazenar 2 linhas:

Esse formato de linha é extremamente eficiente sempre que você faz uma busca em SQL como esta abaixo (típica em ambientes transacionais):

SELECT * FROM CLIENTES WHERE ID = 103

O banco de dados, usando o índice sobre a coluna ID, vai identificar que o bloco 2 possui a linha 103. Esse bloco será colocado em memória (se já não estiver lá), e o bloco será literalmente “varrido” até chegar na linha 103. Neste caso, todas as colunas desta linha serão retornadas na consulta.

Por que esse formato de linha é extremamente eficiente para consultas como essa que mostrei acima?

  • Não importa a quantidade de linhas, com o índice e a estrutura de blocos, o tempo de busca sempre será consistente e próximo do ótimo;
  • O tempo de resposta será geralmente o mesmo não importa se você consultar uma, duas, três ou todas as colunas da tabela: uma vez identificada a linha, todas as colunas desta linha estão fisicamente juntas;
  • Como as linhas estão fisicamente dispostas em centenas ou milhares de blocos diferentes, mesmo com muitos usuários concorrentes é razoável observar que haverá pouca concorrência em cada bloco, logo, esse formato é capaz de suportar uma grande quantidade de usuários simultâneos.

Agora vamos para um outro exemplo onde esse formato de linha não é muito bom. Suponha que fiz a seguinte consulta em SQL:

SELECT CIDADE, COUNT(*) as TOTAL
FROM CLIENTES
WHERE PAIS = 'BRASIL'
GROUP BY CIDADE

Esta consulta funciona com o formato de linhas, mas não é realmente eficiente. Em outras palavras, dependendo de alguns fatores, o desempenho desta consulta pode ser desastroso:

  • Se a quantidade de linhas na tabela for muito grande, a coluna PAÍS poderá não filtrar (restringir) muitos dados, e o banco de dados terá que processar uma grande quantidade de linhas para fazer o COUNT;
  • Se a quantidade de colunas na tabela for muito grande muitas delas serão “varridas”, mas apenas duas serão úteis para o resultado: neste exemplo CIDADE e PAIS;
  • A consulta poderá até retornar poucas linhas, mas terá que ler muitas linhas para compor o resultado, e por isso se houver muitos usuários concorrentes, todos lendo muitas linhas ao mesmo tempo, com certeza todos serão impactados no tempo de resposta (pela concorrência que um usuário gerará sobre os demais usuários);
  • A compressão dos dados não é boa, porque dentro de um mesmo bloco uma linha tem várias colunas de vários tipos (pouca repetição dos dados). Algoritmos de compressão são eficientes quando há bastante repetição dos dados dentro do mesmo bloco.

Nota: geralmente os algoritmos de compressão consideram um bloco de dados como “limite” dos dados a serem usados para compressão, de forma que os valores repetidos em um mesmo bloco seja substituído por ponteiros, economizando espaço.

Em outras palavras, quanto mais restritivas são as consultas (usando filtros pelo índice da chave primária, por exemplo), melhor será o formato de dados orientado por linhas. Quanto menos restritivas, ou seja, quanto maior o volume de dados movimentado pela consulta, pior será este formato.

Organização por Coluna

Vamos entender primeiro quais são as características de um sistema que possui um perfil mais analítico.

Geralmente esse perfil se caracteriza por requisições mais complexas, consultas que agregam muitos dados (relatórios), e com cargas de dados de alto volume, porém, possuem menor concorrência de usuários comparado com os sistemas transacionais.

Para acelerar as consultas, o modelo de dados geralmente é composto por tabelas mais desnormalizadas (dados mais repetidos, sem necessidade de ter que fazer joins), organizadas segundo padrões de design de suporte a decisão, como star schema ou snow flake.

Exemplos típicos onde encontraremos esse tipo de sistema: data warehouses, data marts, data lakes e data lakehouses.

O formato colunar é diametralmente o oposto do formato orientado por linha. Neste formato, os dados são fisicamente organizados pelas colunas, e não pelas linhas:

Na figura podemos ver que os dados de cada coluna são armazenados fisicamente juntos, em blocos diferentes. Isto é, o ID 100 está mais próximo do ID 101 fisicamente do que do nome Maria.

Então consultas que buscam retornar todas as colunas são terríveis neste formato, mesmo filtrando pela chave primária:

SELECT * FROM CLIENTES WHERE ID = 103

Isto ocorre porque neste caso teremos que fazer pelo menos 5 leituras físicas diferentes, uma em cada bloco (sendo que no formato por linha, todas as colunas estão fisicamente no mesmo bloco).

Agora, para consultas com perfil mais analítico, onde buscamos apenas por algumas colunas, e descartamos todas as outras, nada é mais eficiente que o formato colunar:

SELECT CIDADE, COUNT(*) as TOTAL
FROM CLIENTES
WHERE PAIS = 'BRASIL'
GROUP BY CIDADE

Neste exemplo, vamos ler apenas os blocos 4 (CIDADE) e 5 (PAÍS).

Por que esse formato colunar é extremamente eficiente para consultas como essa que mostrei acima?

  • Reduz bastante a quantidade de I/O físico a ser feita, pois o I/O é feito apenas sobre os blocos das colunas usadas na consulta (menos dados para ler);
  • Como os dados do mesmo tipo (mesma coluna) estão juntos, no mesmo bloco, a probabilidade de repetição de valores aumenta, e portanto a compressão dos dados também aumenta (por haver maior repetição dos dados de uma mesma coluna): menos I/O;
  • Muitos bancos de dados usam instruções do tipo SIMD (Single Instruction Multiple Data) nos processadores, fazendo com que com uma única instrução de leitura, o processador seja capaz de ler “várias linhas colunares” ao mesmo tempo, aumentando a performance.

Vale lembrar que o formato dos dados, seja linha ou coluna, é algo físico, e não lógico. Em outras palavras, para o usuário-final, ou o sistema, é transparente: utiliza-se SQL.

Exemplos de Tecnologias para cada Formato de Dados

Alguns exemplos de armazenamento no formato de linha:

  • Bancos de dados: Oracle, SQL Server, MySQL, PostgreSQL;
  • Arquivos: AVRO, CSV.

Alguns exemplos de armazenamento no formato de coluna:

  • Bancos de dados: HBase, Oracle ADW, AWS Redshift, GCP BigQuery;
  • Arquivos: ORC, Parquet.

Existem bancos de dados que fornecem um modelo híbrido entre linha e coluna, onde os dados no formato de linha são replicados para um cache colunar, porém, esta replicação é transparente para o sistema (mesmo endpoint de conexão).

Exemplos de bancos de dados que tem a capacidade híbrida: MySQL HeatWeave e Oracle Database In-Memory.

O formato híbrido permite que um sistema transacional co-exista com cargas de relatórios ao mesmo tempo, sem impacto no desempenho, e sem ter que depender de uma engenharia de dados para movimentar os dados entre meios de armazenamento de formatos diferentes.

Conclusão

É importante entender as características de acesso de um sistema que você está criando para selecionar o formato mais apropriado: que traz boa performance e baixo consumo de armazenamento de dados (compressão).

O formato de linha é melhor para sistemas OLTP, enquanto que o formato colunar é melhor para Data Warehouses, Data Lakes e Data Lakehouses.

O formato híbrido (linha e coluna) é o melhor para casos mistos, onde há nitidamente a necessidade de existir transações e relatórios analíticos sob um mesmo banco de dados.

Publicidade

Um Panorama Sobre os Tipos de Banco de Dados para Você Ficar por Dentro

Sistemas de banco de dados são como vinhos, queijos e árvores. Eles melhoram enquanto envelhecem.


Em um projeto complexo, com requisitos de alta performance, escalabilidade e disponibilidade para a camada de persistência, de todas as decisões que você deve tomar, nenhuma é mais desafiadora – e nenhuma outra tem recebido mais atenção – do que ESCOLHER O BANCO DE DADOS MAIS ADEQUADO [a engenharia do Uber que o diga]. O que torna tal decisão tão difícil não é só a quantidade de opções que existe [são mais de 300 bancos de dados para os mais diversos fins].

Os sistemas Relacionais são os mais populares, suportam nativamente SQL [que é a melhor linguagem para consultar e manipular dados], e são os melhores em integridade – mas sabidamente eles não escalam de forma eficiente, e têm baixa flexibilidade. Os sistemas NoSQL escalam horizontalmente, são extremamente flexíveis e suportam dados variados, mas pecam na consistência [que é eventual]. Os sistemas NewSQL são um avanço dos NoSQL, têm maior consistência, maior suporte ao SQL, porém com menor disponibilidade em relação ao anterior. Os sistemas Multi-Model são uma combinação do Relacional com o NoSQL, porém não absorvem todas as características de arquitetura de cada um. Multi-Model é uma capacidade que todos os anteriores podem ter.

A GRANDE DIFICULDADE está em escolher aquele que atenda aos requisitos atuais, MAS QUE TAMBÉM ATENDA AOS REQUISITOS FUTUROS que você ainda não sabe quais são. Isso pode te deixar na mão se o sistema de banco de dados escolhido não tiver a capacidade de se adequar ao dinamismo que estamos vivenciando, como desenvolvimento ágil, microserviços, aplicações cloud native, machine learning, blockchain e IoT.

Pare por um momento e responda: Você Tem Dúvidas para Decidir Qual é a Camada de Persistência Mais Adequada para seu Próximo Projeto? Espero que este panorama lhe ajude a ter uma visão mais clara.

Relacional é SQL, e SQL é Relacional: uma Simbiose dos Anos 70 que é Atual até Hoje

SQL e o sistema de banco de dados Relacional transformaram em museu rapidamente tudo que existia antes. Inovações como acesso client/server, joins, locks no nível de linha, leitura consistente, transações locais e distribuídas, e constraints, só para citar alguns, foram capazes de aliviar os desenvolvedores da época, e substituir milhares de linhas de código por uma simples frase: SELECT FROM WHERE. A evolução do SQL foi um dos acontecimentos mais importantes na década de 80 na área de tecnologia, pois mudou a forma como a informação era utilizada, e como os sistemas eram construídos.

A linguagem SQL e o sistema Relacional surgiram, e milhares de linhas de código foram substituídas por uma simples frase: SELECT FROM WHERE.

A linguagem SQL, utilizada para buscar e manipular dados em um banco Relacional, é amplamente “simulada” sob outros formatos NoSQL, porque, no final do dia, SQL é uma das linguagens mais simples do universo!

Hoje em dia SQL é extremamente robusto: ele permite não só consultar e manipular dados, mas também permite fazer data wrangling de forma muito eficiente, fornece capacidade nativa para reconhecimento de padrões, expressões regulares, aprendizado de máquina, funções analíticas, e possui uma biblioteca de APIs bastante abrangente em todas as implementações de banco de dados.

A Força Bruta de Consistência

Outra característica marcante nos sistemas Relacionais é a INTEGRIDADE. Quando o objetivo é integridade, nada construído até hoje é mais rápido e mais simples do que o sistema de banco de dados Relacional. Há quase 40 anos ele tem sido o padrão para armazenamento na maioria dos sistemas de informação, porque a maioria dos sistemas precisa de integridade.

As propridades ACID [Atomicidade, Consistência, Isolamento e Durabilidade] são os fundamentos da integridade nos sistemas Relacionais, e ao lado da linguagem SQL, são vistas como as principais características deste modelo de persistência.

ATOMICIDADE: se uma transação tem vários comandos, ou faz tudo, ou não faz nada; CONSISTÊNCIA: a transação respeita a unicidade da chave primária, o valor que não pode ser nulo, a chave estrangeira, os datatypes e quaisquer outras regras definidas na tabela; ISOLAMENTO: uma transação não enxerga a outra que atua no mesmo dado. Um produto tem 1 unidade e duas compras são realizadas ao mesmo tempo: uma deve executar primeiro. Se a primeira efetivar, a segunda não consegue comprar o produto [por falta de estoque]. Se a primeira falhar, a segunda efetiva a compra do produto; DURABILIDADE: o dado alterado por uma transação persiste em disco, e este sempre será o mesmo até que outra transação válida o altere.

Para garantir a integridade em transações distribuídas, os sistemas Relacionais utilizam o protocolo Two-Phase Commit, conhecido como 2PC, para garantir a atomicidade [A do ACID].

Quando uma transação é distribuída entre vários bancos de dados, quando um deles faz commit, todos votam, e caso todos votem ‘sim’, eles registram o commit em logs locais – ou rollback, caso pelo menos um vote ‘não’, ou haja qualquer falha [fase 1]. Supondo que todos votem ‘sim’, a confirmação é retornada para todos, e a transação é efetivada em todos os bancos de dados [fase 2]. O log de confirmação local garante que todos podem exercer o commit, caso haja uma falha durante fase 2.

O modelo relacional é schema-full. Isto significa que a estrutura das tabelas [colunas, datatypes e constraints] precisa estar definida antes dos dados serem gravados. É como um contrato entre quem vai ler e quem escrever no banco de dados.

A característica schema-full, as propriedades ACID, e o protocolo 2PC são os alicerces da integridade no sistema de banco de dados Relacional. Há outros acessórios [como as leituras consistentes e o MVCC] para melhorar a experiência do usuário diante da força bruta de consistência disponível.

Há Certas Coisas que os Sistemas Relacionais Não Fazem por Você

Os TRADE-OFFS mais importantes dos sistemas Relacionais são, em primeiro lugar, A FALTA DE FLEXIBILIDADE DO FORMATO DE DADOS, e depois, A BAIXA CAPACIDADE DE ESCALAR no nível da internet.

A FALTA DE FLEXIBILIDADE foi na verdade uma vantagem do modelo Relacional nos anos 80-90 [quando os desenvolvedores tinham que fazer o schema na mão]: o modelo de dados é schema-full. Isto é, primeiro é necessário criar a estrutura dos dados, para depois inserí-los, e não o oposto [como ocorrem com os NoSQL]. Há vantagens na abordagem schemaless, principalmente nos tempos atuais, e portanto, hoje, não tê-la é um ponto negativo [mais adiante eu falo sobre Multi-Model, que torna o sistema Relacional mais moderno].

A BAIXA CAPACIDADE DE ESCALAR ocorre porque, em geral, nos sistemas Relacionais, os dados das tabelas não são distribuídos entre servidores distintos e independentes [shared-nothing], e por isso eles apenas escalam verticalmente [até a capacidade de um servidor, e não de vários] – esse é um forte limitador de escalabilidade.

Há, entretanto, uma implementação de software ainda única, da Oracle [chamada Oracle RAC], que permite que vários servidores ativos e distintos acessem os arquivos de um mesmo banco de dados [shared-disk], mantendo a consistência forte. No teorema CAP que explico mais adiante, o RAC recebe a classificação CA [consistency e availability]: essa tecnologia é a que mais oferece escalabilidade para um sistema de banco de dados Relacional, mas ainda é inferior aos níveis de escalabilidade oferecidos pelos NoSQL.

VOCÊ DEVE CONSIDERAR O SISTEMA DE BANCO DE DADOS RELACIONAL PARA DADOS QUE PRECISAM DE INTEGRIDADE.

Os Sistemas NoSQL são como Albatrozes: Ágeis no Ar, mas Desajeitados em Terra

Apesar de tanta inovação e robustez para gerenciar dados, por causa da internet, o modelo de infraestrutura que só escala verticalmente [para cima], como ocorre com os bancos de dados Relacionais, demonstrou não atender a escalabilidade necessária para suportar aplicações web de OLTP intenso: milhões de usuários com demandas variáveis e imprevisíveis.

No ano 2000 surgiram as primeiras tecnologias NoSQL que ganharam escala. Fizeram muito sucesso como forma de persistência nas redes sociais, e começaram a ganhar espaço nas empresas.

Os bancos de dados NoSQL, de forma geral, são baseados em estruturas de dados schemaless, em arquitetura shared-nothing [totalmente distribuído, nada é compartilhado], e por isso conseguem escalar horizontalmente [para os lados] e armazenar qualquer estrutura de dados. Há muitas implementações de NoSQL, sendo que as principais são Chave-Valor, Documentos, Grafos e Orientado a Coluna.

A implementação Chave-Valor é indicada para leitura ou escrita intensiva de qualquer coisa, não importa o formato, desde que seja com o maior throughput possível. A implementação de Documentos é indicada para manipular informações que são agrupadas e relacionadas, como um catálogo de produtos, por exemplo. Grafos é indicada para dados altamente conectados, para encontrar conexões entre pessoas e coisas. Orientado a Coluna é um híbrido do formato linha e coluna, e é indicado para altos volumes de dados, em especial para escrita [não tanto para consulta].

Você precisa entender o Teorema CAP [Consistency, Availability, Partition Tolerance] e sua importância no mundo dos sistemas distribuídos. Ele prova que um sistema que distribui seus dados em servidores diferentes [sem compartilhar qualquer componente de infraestrutura], não pode ter disponibilidade e consistência ao mesmo tempo. No advento de uma falha na rede ou em um servidor qualquer, a CONSISTÊNCIA É GARANTIDA [letra C do CAP, onde um leitor enxerga todas as escritas completadas previamente], ou a DISPONIBILIDADE É GARANTIDA [letra A do CAP, onde o sistema sempre estará disponível para leitura/escrita], e não ambos.

Em geral, os sistemas NoSQL suportam AP [A de Availability, e P de Partition Tolerance]: sempre que há escrita em um servidor, ela é replicada de forma assíncrona para outros servidores espelho para manter a disponibilidade da informação – todos os servidores, os que escrevem, e os que recebem as escritas replicadas, ficam disponíveis para leitura.

Como exemplo, em uma configuração de cluster com 10 servidores, em geral 5 permitem escrita, e os outros 5 permitem apenas leitura. Nesta configuração, cada servidor-escritor replica de forma assíncrona para seu par que só permite leitura. Cada conjunto escritor/leitores são completamente independentes de outros conjuntos escritor/leitores, e cada um desses conjuntos armazena uma parte da informação.

Se houver falha em um servidor, os demais servidores espelho continuam lendo ou escrevendo, mesmo que possa haver inconsistência: a falha impede que um servidor replique seus dados para as outros servidores espelho. Desta forma, quando se lê um dado nesta situação, ele estará eventualmente consistente. Isso ocorre porque o dado poderá ter sido alterado, mas esta alteração pode não ter sido propagada para as réplicas. Além disso, mesmo sem uma falha, como as replicações são assíncronas, é possível que uma leitura em uma réplica possa não estar enxergando a versão mais recente da informação. Logo, haveria também uma leitura eventualmente consistente.

Ao contrário dos sistemas AP, os sistemas CP privilegiam a consistência forte. Um servidor-escritor envia os dados de forma síncrona para os seus respectivos servidores espelho. Então, se você está lendo a partir do servidor que escreve, ou da réplica, você sempre estará lendo a informação mais recente. Isso é consistência forte. Entretanto, se um servidor que escreve tem uma falha e fica indisponível, os seus pares ficam impossibilitados de escrever para evitar um cenário de inconsistência. Por isso, uma parte da informação torna-se inacessível, porém não o sistema todo: apenas os servidores com falha.

Esse é o trade-off entre AP e CP. E não é possível um sistema de banco de dados ter C, A e P ao mesmo tempo, conforme prova o teorema.

Tanto os sistemas AP, como os CP, dizem ter Consistência. Mas é importante entender que existem dois tipos de Consistência: a Forte, onde um leitor enxerga todas as escritas feitas previamente; e a Eventual, onde um leitor pode ou não, isto é, eventualmente, enxergar as escritas feitas previamente. Além disso, existe a Consistência no ACID, que tem a ver com integridade do dado escrito [datatypes, null ou not null, constraints, etc], e também existe a Consistência no CAP, que indica se a informação que um leitor lê é, ou não, a versão mais recente.

Consistência eventual para as redes sociais, ok! Para os batches… humm, talvez. Para as aplicações online? Complicado…! Neste caso, se necessário, o desenvolvedor que deve garantir a consistência forte em um sistema AP, já que ela não está disponível nesse tipo de banco de dados – e vale lembrar que é muito complexo codificar consistência: não é exatamente para qualquer um! É uma codificação altamente suscetível a bugs [lembra quando falei sobre as inovações do sistema Relacional? Os NoSQL descartam várias delas, a consistência forte é um exemplo].

Quanto mais os bancos de dados NoSQL se aproximam das aplicações online nas empresas, maior é a necessidade de transações, ACID, e consistência forte.

Não é exatamente uma desilução dos NoSQL que suportam AP, pois eles ainda têm seu lugar em diversos casos de uso. Mas está cada vez mais comum a introdução de capacidades CP [consistência] nas tecnologias que outrora iniciaram sua implementação com AP.

Um outro ponto relevante é que nenhum sistema garante efetivamente 100% de disponibilidade [o A do CAP]. Na prática há alguns 9s de disponibilidade, mas nunca 100% [você pode ter 20 réplicas, mas embora difícil, não é impossível perder todas elas]. Então o A do CAP é apenas “teórico”, mesmo para os NoSQL AP, que notadamente sacrificam a consistência para supostamente garantir 100% da disponibilidade. De fato, tanto a consistência quanto a disponibilidade são sacrificadas nos sistemas NoSQL AP.

E para complicar um pouco mais, AP sempre sacrifica a consistência, pois em virtude da necessidade de baixa latência [lê-se replicação assíncrona], os dados em geral sempre estarão eventualmente consistentes, mesmo sem uma falha ou falta de comunicação na rede.

VOCÊ DEVE CONSIDERAR UM SISTEMA DE BANCO DE DADOS NOSQL QUANDO ESCALABILIDADE FOR MUITO MAIS IMPORTANTE DO QUE INTEGRIDADE, DO CONTRÁRIO, CONSIDERE O RELACIONAL.

Obrigado pela Ajuda NoSQL: Agora é com a Gente!

A necessidade real nas empresas para atender as demandas de escalabilidade atuais é Consistência Forte [do SQL] com Escalabilidade Horizontal Distribuída [do NoSQL]. Eis então que surgem os bancos de dados NewSQL!

O título desta parte do meu artigo é originalmente do post de um blog do MemSQL, que faz uma sátira com os bancos de dados NoSQL, em favor do deles, um banco de dados NewSQL. E eles ainda completam: “Tá na hora de admitirmos o que todos nós já sabíamos por muito tempo: NoSQL é a ferramenta errada para muitos casos de usos nas aplicações modernas, e está na hora de seguirmos em frente.

O texto do post começa explicando a ascensão da tecnologia NoSQL diante das supostas limitações da tecnologia SQL para os sistemas mais modernos, digitais e cloud native. Na sequência é introduzida a tecnologia NewSQL, que emerge dos pontos positivos do SQL e NoSQL combinados, o que acaba por colocar em decadência as tecnologias só-NoSQL, e também só-SQL.

De fato, SQL fez emergir NoSQL, que fez emergir NewSQL. E os sistemas NewSQL são então, mais do que nunca, gratos pela contribuição dos NoSQL, que os fez surgir, daí o título ligeiramente escrachado do post.

A diferença mais notável entre um NoSQL e um NewSQL é que o último suporta consistência forte, e na melhor da boa vontade, SQL e outras características do sistema Relacional. Os sistemas de informação nas empresas não são Facebooks, Instagrams, Twitters. Elas precisam de consistência. Então sim, NewSQL ascende. NoSQL, decai.

Os sistemas NewSQL representam uma evolução em relação aos NoSQL, oferecendo suporte a CP do CAP. NewSQL tenta ser um SQL, e tolera partições de rede, a grande diferença. A tolerância a partição permite escalar horizontalmente, como os NoSQL, e entrega escalabilidade ao nível da internet.

Mas francamente, quase todos os NewSQL, ou todos realmente, não suportam SQL plenamente. Não há como ignorar quase 4 décadas de desenvolvimento. Todos os NewSQL suportam apenas uma porção do que os sistemas SQL tradicionalmente suportam: compliance ao ANSI plenamente, extensões proprietárias, ACID, 2PC, Multi-Model, segurança abrangente de dentro pra fora, backups e restores granulares, monitoração robusta com grande poder de instrumentação, e milhares de outras características.

É apreciável o esforço de construir uma consistência nativa bem elaborada numa arquitetura dominada por Albatrozes que voam bem, mas pousam terrivelmente mal [aqui eu me refiro aos NoSQL].

VOCÊ DEVE CONSIDERAR UM SISTEMA DE BANCO DE DADOS NEWSQL QUANDO ESCALABILIDADE FOR MUITO RELEVANTE, TÃO QUANTO INTEGRIDADE, DO CONTRÁRIO, CONSIDERE ALGUM DOS ANTERIORES.

Não é um Pato, é Multi-Model

Os sistemas de banco de dados Multi-Model são aqueles que permitem nativamente vários formatos ao mesmo tempo, como Relacional, Grafos, Chave-valor, Documentos, Colunar e qualquer outro que se torne relevante.

A característica Multi-Model se torna relevante principalmente nos tempos atuais, onde as aplicações podem requerer persistência poliglota, isto é, um sistema de banco de dados diferente para cada parte da aplicação, já que cada um é melhor em algum caso específico.

A verdade é que sempre existe aquele sistema de banco de dados “cutting-edge“, de ponta, de última geração, crème de la crème. Aquele que só ele faz aquilo que ele faz. Mas o que também ocorre é que se aquilo que só ele faz se torna relevante, os sistemas de banco de dados multi-model o absorvem. Tem sido assim nos últimos anos, e provavelmente sempre será.

As inovações dos sistemas Single-Model são incorporadas nos sistemas Multi-Model

Desenvolver um banco de dados é muito complexo. Um exemplo disso é o bem difundido PostgreSQL [com suas limitações de escalabilidade], que fez por exemplo o Uber deixar de usá-lo, conforme mencionei no início deste artigo. É mais simples e rápido incorporar features novas do que construir todo um core, e é por isso que os sistemas de banco de dados Multi-Model ainda dominam.

VOCÊ DEVE CONSIDERAR UM SISTEMA DE BANCO DE DADOS MULTI-MODEL QUANDO FLEXIBILIDADE DE SCHEMA E CONSISTÊNCIA FOREM AMBOS MUITO IMPORTANTES.

Há Uma Coisa em Comum entre os Duendes que Vivem Embaixo da sua Cama, e os Bancos de Dados Schemaless

Ambos não existem!


Do ponto de vista da aplicação, na prática, schemaless não existe.

Schemaless, ou schema on read, é quando não existe a estrutura de dados definida [colunas, datatypes, constraints] quando se escreve, pois quem a define é quem lê [a aplicação]. O oposto é Schema-full, ou schema on write, normalmente utilizado pelos bancos de dados Relacionais: define-se a estrutura, e depois insere os dados.

Provavelmente a fábula do schemaless parece ter sido criada por desenvolvedores de front-end que, supostamente, teriam muito mais agilidade para desenvolver e mudar as aplicações sem depender do banco de dados [e seus agregados, como DBAs, indisponibilidade, processos de mudança, etc].

Mas a realidade não é bem assim: tudo SEMPRE tem schema, e se tem schema, mudanças SEMPRE têm esforço.

Schema é o conjunto de regras de integridade que você define para organizar os dados. O sufixo full é quando o BANCO DE DADOS exerce o schema, e o sufixo less é quando VOCÊ exerce. SEMPRE ALGUÉM EXERCE O SCHEMA.

Nos últimos 30 anos os principais bancos de dados criaram mecanismos para implementar recursos de integridade com escalabilidade e disponibilidade. Em alguns bancos de dados é possível fazer alterações de estrutura com zero downtime para a aplicação, e mesmo assim garantir toda a integridade.

Não há como uma aplicação não ter schema. Se você utiliza um Document Store por exemplo, onde os dados persistem como documentos JSON [logo, schemaless], a aplicação tem que saber como ler esses documentos. Saber como ler significa ter schema. Quando você lê um documento JSON e extrai dele um valor numérico para fazer um cálculo, terá que convertê-lo para int, float ou Decimal [um type, logo, um schema]. A propósito, Python é uma linguagem dinamicamente tipada, e mesmo que você não especifique o type estaticamente enquanto programa, deve especifica-lo mentalmente [logo, um schema] para não gerar erro durante a execução.

No final do dia, quando você entende que sempre existe um schema, não há nada que um banco de dados schemaless faça com mais agilidade do que um banco de dados schema-full. A questão é se você quer deixar que o banco de dados exerça o schema por você, ou você adia o trabalho inevitável de VOCÊ exercer o schema depois.  

Eu tenho uma preferência particular por bancos de dados Multi-Model, pois há situações onde o uso conjunto da persistência Relacional e Documentos oferece o melhor da flexibilidade com o melhor da integridade.