flowchart TD
A[Aplicacao ou usuario envia SQL] --> B[Processador de consultas]
B --> C[Parser e analise semantica]
B --> D[Otimizador de consultas]
B --> E[Motor de execucao]
E --> F[Gerenciador de transacoes]
E --> G[Gerenciador de buffer]
G --> H[Gerenciador de armazenamento]
F --> I[Gerenciador de recuperacao e log]
H --> J[(Arquivos em disco)]
I --> J
K[Dicionario de dados] --- B
K --- F
K --- H
Arquitetura de SGBDs relacionais
Quando você digita um simples SELECT e o resultado aparece na tela em milissegundos, há por trás uma orquestra de componentes de software trabalhando em conjunto. Neste módulo eu quero abrir a “tampa” do motor e te mostrar como um Sistema Gerenciador de Banco de Dados (SGBD) relacional é arquitetado por dentro. Esse é um tema que cai com frequência em prova porque amarra tudo o que você já estudou: o caminho que uma consulta percorre, como as transações são protegidas, como os dados ficam organizados no disco e, sobretudo, a famosa arquitetura de três esquemas da ANSI/SPARC. Vou conduzir você camada por camada, do nível físico ao lógico, e depois te mostrar como esse projeto se estende para os mundos distribuído, paralelo e in-memory. Repare comigo que a arquitetura não é um detalhe de implementação acadêmico: é o que explica por que esses sistemas são confiáveis, rápidos e duradouros há mais de cinquenta anos.
O que entendemos por arquitetura de um SGBD
Falar de arquitetura é falar de organização: quais peças existem, o que cada uma faz e como elas conversam. Um SGBD relacional não é um programa monolítico; ele é um conjunto de subsistemas especializados, cada um responsável por uma fatia bem definida do trabalho de gerenciar dados. Eu gosto de pensar nisso como uma fábrica. Há um setor que recebe e interpreta os pedidos (as consultas SQL), um setor que planeja a melhor forma de produzir, um setor que cuida da memória de trabalho, um setor que organiza o estoque no almoxarifado (o disco) e um setor de segurança e auditoria que garante que nada se perca em caso de incêndio. Quando essas partes funcionam em harmonia, o resultado é desempenho, consistência e durabilidade.
Definição. A arquitetura de um SGBD descreve seus componentes internos, suas responsabilidades e suas interações, além de como os dados são representados em diferentes níveis de abstração — do esquema visto pelo usuário até a organização física em blocos de disco.
Os componentes de um SGBD relacional
Vou começar mapeando as peças. Pense numa pilha de camadas: no topo chegam os comandos, e na base estão os bits no disco. Entre os dois extremos ficam os gerenciadores que fazem a ponte.
O processador de consultas é a porta de entrada. Ele recebe o texto SQL, verifica se a sintaxe está correta no parser, confere no analisador semântico se as tabelas e colunas citadas existem e se você tem permissão para acessá-las, e então entrega o trabalho ao otimizador. O otimizador é, na minha visão, o componente mais engenhoso de todo o sistema: ele gera vários planos de execução possíveis para a mesma consulta e escolhe o de menor custo estimado, considerando estatísticas sobre os dados, índices disponíveis e os custos de leitura em disco e de processamento. Em seguida o motor de execução percorre esse plano, pedindo páginas de dados às camadas inferiores.
O gerenciador de transações garante que toda unidade lógica de trabalho respeite as propriedades ACID, coordenando bloqueios ou versões (MVCC) para que transações concorrentes não se atrapalhem. O gerenciador de buffer mantém em memória RAM as páginas mais acessadas, evitando ir ao disco a cada operação — é uma camada de cache decisiva para o desempenho. Logo abaixo, o gerenciador de armazenamento cuida da organização física: aloca espaço, mantém os índices em disco e executa o I/O de baixo nível. O gerenciador de recuperação registra cada mudança num log antes de aplicá-la (o Write-Ahead Logging) e usa esse log mais os checkpoints para reconstruir um estado consistente após uma falha. Costurando tudo, há o dicionário de dados (ou catálogo), uma base de dados sobre o próprio banco: ele guarda as definições de tabelas, colunas, tipos, restrições, visões, índices, usuários e privilégios. Todo componente consulta o dicionário o tempo todo.
| Componente | Responsabilidade central | Trabalha junto com |
|---|---|---|
| Parser / analisador | Validar sintaxe e semântica do SQL | Dicionário de dados |
| Otimizador | Escolher o plano de execução de menor custo | Estatísticas e dicionário |
| Motor de execução | Executar o plano e produzir resultados | Buffer e armazenamento |
| Gerenciador de transações | Garantir ACID e isolamento | Recuperação e log |
| Gerenciador de buffer | Cache de páginas em RAM | Armazenamento |
| Gerenciador de armazenamento | Organização física, alocação, I/O | Disco |
| Gerenciador de recuperação | Log, checkpoint, redo/undo | Buffer e disco |
| Dicionário de dados | Metadados do banco | Todos os demais |
O caminho de uma consulta: do parse à execução
Quero agora seguir uma consulta passo a passo, porque entender esse fluxo é entender o coração do SGBD. Imagine que você submeteu o comando abaixo.
O que acontece com ela? O texto primeiro vira uma árvore. Depois essa árvore é validada, reescrita numa forma equivalente mais eficiente, otimizada com escolha de índices e métodos de junção, traduzida num plano de baixo nível e finalmente executada. Veja o percurso completo.
flowchart LR
A[SQL recebido] --> B[Parsing sintatico]
B --> C[Analise semantica e permissoes]
C --> D[Reescrita da consulta]
D --> E[Otimizacao baseada em custo]
E --> F[Geracao do plano de execucao]
F --> G[Execucao no motor]
G --> H[Acesso a dados via buffer e disco]
H --> I[Resultado retornado]
Na etapa de otimização, o sistema decide questões como: vale a pena varrer a tabela pedido inteira ou usar um índice em cliente_id? A junção deve ser feita com nested loop, merge join ou hash join? Convém aplicar o filtro cidade = 'São Paulo' antes da junção, reduzindo o volume de linhas que entram nela? Esse último truque, empurrar o predicado para perto da fonte dos dados, chama-se pushdown de predicados e quase sempre acelera a consulta. O otimizador também pode reordenar junções para minimizar o tamanho dos resultados intermediários — a ordem em que combinamos as tabelas tem impacto enorme no custo.
Atenção. A consulta SQL é declarativa: você diz o que quer, não como obter. Quem decide o “como” é o otimizador. Por isso duas consultas com o mesmo resultado podem ter desempenho radicalmente diferente, e por isso manter estatísticas atualizadas é tão importante — elas alimentam as estimativas de custo.
Arquitetura física: arquivos, páginas, blocos e registros
Vamos descer ao subsolo, onde os dados realmente moram. No nível físico, o banco é um conjunto de arquivos no sistema de arquivos do sistema operacional. Esses arquivos são divididos em páginas (também chamadas de blocos), tipicamente de 4 KB a 16 KB. A página é a unidade mínima de transferência entre disco e memória: quando o SGBD precisa de um único registro, ele traz a página inteira que o contém para o buffer. Cada página tem um cabeçalho com metadados (identificador, checksum), uma área com os registros de dados, ponteiros e um espaço livre reservado para crescimento.
flowchart TD
A[Banco de dados] --> B[Arquivo de dados]
B --> C[Pagina ou bloco de 4KB a 16KB]
C --> D[Cabecalho com metadados]
C --> E[Registros das tuplas]
C --> F[Espaco livre]
E --> G[Campos de cada registro]
A forma como as páginas de uma tabela são organizadas define a estratégia de acesso. Num heap file, os registros entram na ordem de chegada, sem ordenação — é ótimo para inserir rápido, mas péssimo para buscar sem índice. Num arquivo ordenado, mantém-se a ordem por uma chave, o que acelera buscas por intervalo mas encarece inserções. No hashing, uma função distribui os registros em buckets, perfeito para busca por igualdade. E há o armazenamento orientado a coluna, em que cada coluna é guardada separadamente, ideal para análises que tocam poucas colunas de muitíssimas linhas.
É aqui também que vivem os índices, estruturas auxiliares que aceleram a localização de registros. A B+Tree é a campeã absoluta porque atende bem tanto buscas por igualdade quanto por intervalo, mantendo-se balanceada. Já o índice hash só serve à igualdade, e o índice bitmap brilha em colunas de baixa cardinalidade.
| Organização | Forte em | Fraca em |
|---|---|---|
| Heap file | Inserção rápida | Busca sem índice |
| Arquivo ordenado | Busca por intervalo | Manter ordem em inserções |
| Hashing | Busca por igualdade | Busca por intervalo |
| Orientado a coluna | Consultas analíticas | Atualização de linhas inteiras |
Como o acesso a disco é o maior gargalo, o gerenciador de buffer aplica políticas como a substituição LRU (descartar a página menos recentemente usada) e o prefetching (antecipar páginas). E aqui entra um princípio que você precisa gravar: o Write-Ahead Logging exige que toda alteração seja registrada no log antes de ser gravada na página de dados. É esse protocolo que torna a durabilidade possível mesmo quando a energia cai no meio de uma escrita.
Arquitetura lógica e os três esquemas da ANSI/SPARC
Agora subimos de volta para a abstração mais importante deste módulo. Em 1975, o comitê ANSI/SPARC propôs uma arquitetura de três níveis de esquema que até hoje é a espinha dorsal conceitual de qualquer SGBD relacional. A ideia é separar como o usuário vê os dados, como o banco os organiza logicamente e como eles são fisicamente armazenados. Essa separação é o que dá ao sistema sua flexibilidade lendária.
flowchart TD
A[Nivel externo: visoes de cada grupo de usuarios] --> B[Nivel conceitual: esquema logico global]
B --> C[Nivel interno: estruturas fisicas em disco]
A -. independencia logica .-> B
B -. independencia fisica .-> C
No nível externo ficam as visões: cada grupo de usuários enxerga apenas a parte do banco que lhe interessa, com detalhes desnecessários ocultados. No nível conceitual mora o esquema lógico completo — todas as tabelas, colunas, relacionamentos e restrições do banco, independente de implementação física. No nível interno estão as estruturas de armazenamento reais: arquivos, índices, métodos de acesso, organização das páginas. Um esquema é essa descrição estrutural; já a instância é o estado concreto dos dados num dado momento. O esquema muda raramente; a instância muda a cada INSERT ou UPDATE.
O nível externo se materializa em SQL através de visões. Veja como eu criaria uma visão que expõe a uma equipe de marketing apenas os clientes ativos de São Paulo, sem revelar colunas sensíveis.
A equipe consulta vw_clientes_sp como se fosse uma tabela, sem nunca tocar na tabela base nem ver as colunas financeiras. Isso resolve segurança e simplicidade de uma vez só.
Definição-chave: independência de dados. É a capacidade de alterar um nível sem afetar os níveis superiores. A independência lógica permite mudar o esquema conceitual (por exemplo, adicionar uma coluna a uma tabela) sem quebrar as visões e aplicações existentes. A independência física permite mudar o esquema interno (reorganizar índices, trocar o método de acesso) sem afetar o esquema conceitual. É essa propriedade que deixa o banco evoluir por anos sem reescrever os sistemas que dependem dele.
Observe na figura que a independência lógica fica na fronteira entre o externo e o conceitual, e a independência física entre o conceitual e o interno. Na prática, a independência física é mais fácil de obter; a lógica é mais difícil, porque alterações no esquema conceitual costumam ter eco nas aplicações. Esse é um ponto que examinadores adoram inverter para te confundir, então fixe bem qual independência protege qual fronteira.
Arquiteturas avançadas e como o sistema se distribui
A arquitetura que descrevi até agora é, em essência, centralizada: um único processo, um único servidor, tudo num lugar só. SQLite é o exemplo clássico — ele nem servidor tem, roda embutido na própria aplicação e guarda todo o banco num único arquivo. Mas as demandas modernas de escala e disponibilidade levaram a arranjos mais sofisticados. Vou te mostrar a evolução.
flowchart TD
A[Centralizada: tudo em um servidor] --> B[Cliente-servidor: clientes pedem, servidor processa]
B --> C[Distribuida: dados fragmentados em varios nos]
B --> D[Paralela: varios processadores no mesmo sistema]
C --> E[In-memory e NewSQL: alto desempenho e escala]
D --> E
Na arquitetura cliente-servidor, que domina o mercado, o servidor do banco roda numa máquina dedicada e várias aplicações clientes se conectam a ele pela rede, enviando SQL e recebendo resultados. A arquitetura distribuída vai além: os dados são fragmentados (horizontalmente, dividindo linhas; ou verticalmente, dividindo colunas) e espalhados por múltiplos nós, possivelmente em locais geográficos diferentes, muitas vezes com replicação para tolerância a falhas. O grande desafio aqui é manter a consistência: transações que tocam vários nós usam o protocolo de confirmação em duas fases (Two-Phase Commit) para garantir que ou todos confirmam, ou todos desfazem. O sistema também busca transparência, escondendo do usuário que os dados estão fragmentados, replicados e espalhados.
A arquitetura paralela usa vários processadores dentro do mesmo sistema para acelerar o trabalho. Costumamos classificá-la pelo compartilhamento de recursos: shared-memory (processadores compartilham memória, comunicação rápida mas escala limitada), shared-disk (memória própria, disco comum) e shared-nothing (cada nó tem memória e disco próprios, altamente escalável — é o modelo preferido dos sistemas massivamente paralelos). O paralelismo pode ocorrer dentro de uma consulta (dividindo uma junção entre núcleos) ou entre consultas (rodando várias ao mesmo tempo).
Por fim, as arquiteturas in-memory mantêm os dados primariamente na RAM, eliminando a latência de disco e oferecendo desempenho de ordens de magnitude superior — o SAP HANA é o exemplo emblemático. Como a memória é volátil, esses sistemas ainda gravam log em disco para garantir durabilidade. E há a classe NewSQL, que busca a escalabilidade horizontal do NoSQL sem abrir mão das garantias ACID, usando shared-nothing, protocolos de consenso como Paxos ou Raft e MVCC.
| Arquitetura | Característica central | Exemplo |
|---|---|---|
| Centralizada / embutida | Tudo num processo único | SQLite |
| Cliente-servidor | Servidor dedicado, clientes via rede | PostgreSQL, MySQL, SQL Server |
| Distribuída | Dados fragmentados e replicados em nós | Google Cloud Spanner |
| Paralela | Vários processadores no mesmo sistema | Oracle RAC, IBM Db2 |
| In-memory | Dados primariamente em RAM | SAP HANA |
| NewSQL | Escala horizontal com ACID forte | Spanner, sistemas shared-nothing |
Esses exemplos não são puros: o Oracle combina paralelismo, in-memory e clustering; o PostgreSQL é cliente-servidor extensível com replicação; o Amazon Aurora separa armazenamento e computação na nuvem. O que você precisa perceber é que todos partem do mesmo núcleo arquitetural — processador de consultas, gerenciadores de transação, buffer, armazenamento e recuperação — e o estendem para vencer desafios de escala, disponibilidade e desempenho.
Síntese para a prova
Vou amarrar os pontos que mais caem. Um SGBD relacional é composto por componentes especializados que conversam: o processador de consultas (com parser, otimizador e motor de execução), o gerenciador de transações (garante ACID e isolamento via locks ou MVCC), o gerenciador de buffer (cache de páginas em RAM, política LRU), o gerenciador de armazenamento (organização física e I/O), o gerenciador de recuperação (Write-Ahead Logging e checkpoints) e o dicionário de dados (metadados de tudo). O caminho de uma consulta vai do parsing à análise semântica, reescrita, otimização baseada em custo, geração do plano e execução — lembre que o SQL é declarativo e quem decide o “como” é o otimizador.
No nível físico, dados moram em arquivos divididos em páginas de 4 KB a 16 KB, contendo registros; índices B+Tree aceleram buscas por igualdade e intervalo. O conceito mais cobrado é a arquitetura de três esquemas ANSI/SPARC: nível externo (visões), conceitual (esquema lógico global) e interno (estruturas físicas). Daí derivam a independência lógica (mudar o conceitual sem afetar as visões) e a independência física (mudar o interno sem afetar o conceitual) — não troque as duas. As CREATE VIEW implementam o nível externo, garantindo segurança e simplicidade. Por fim, conheça as arquiteturas centralizada, cliente-servidor, distribuída (com fragmentação, replicação e Two-Phase Commit), paralela (shared-memory, shared-disk, shared-nothing) e in-memory, sabendo associar cada uma a exemplos como SQLite, PostgreSQL, Spanner e SAP HANA.