Série: Construindo um Sistema de Banco de Dados Simplificado

Parte 1: Introdução e Arquitetura do Sistema

Descubra os fundamentos por trás de engines de banco de dados com uma implementação didática em Elixir, passo a passo, desde a arquitetura até consultas SQL.

Nesta série, seguiremos passo a passo o tutorial disponível em:

para construir do zero um sistema de banco de dados simplificado em Elixir. Nosso objetivo é entender os conceitos fundamentais por trás de engines como PostgreSQL, mas com implementações didáticas.

Objetivos Gerais da Série

  1. Implementar o mecanismo de armazenamento (storage engine) baseado em páginas fixas.
  2. Criar um parser SQL básico usando NimbleParsec para converter consultas em AST.
  3. Desenvolver um planner simples que gere planos de execução a partir da AST.
  4. Construir um executor capaz de realizar operações de leitura e escrita em arquivos de dados.
  5. Adicionar uma estrutura de índices (ex.: B-Tree) para acelerar buscas.
  6. Oferecer uma interface REPL para executar comandos SQL interativamente.

1. Arquitetura Geral do Sistema

Inspirados no repositório “build-a-simple-database-from-scratch” (zsxh), adotaremos uma arquitetura em camadas que abrange os seguintes subsistemas:

  • Catalog Manager (DB.Catalog): mantém metadados sobre tabelas, colunas, índices e esquemas. Operações de criação, alteração e consulta de objetos do banco.
  • Storage Manager (DB.Storage): gerencia o acesso físico ao arquivo de dados, baseado em páginas fixas. Inclui:
    • Buffer Pool (DB.Storage.Buffer): cache de páginas em memória, com política de substituição LRU.
    • Disk Manager (DB.Storage.Disk): leitura/escrita de páginas no disco.
  • Record Manager (DB.Storage.Record): empacota e desempacota tuplas em páginas, cuida de offsets e free space.
  • Index Manager (DB.Index): implementação de B-Tree simplificado, suportando pesquisas e inserções em índices.
  • Transaction Manager (DB.Transaction): controle de concorrência (locks simples) e gerenciamento de logs para recuperação básica (Write-Ahead Logging).
  • Parser (DB.Parser): converte consultas SQL em AST usando NimbleParsec.
  • Optimizer/Planner (DB.Planner): gera planos lógicos e físicos (Seq Scan, Index Scan), com estimativas de custo simples.
  • Executor (DB.Executor): percorre o plano de execução, chama Record Manager e Index Manager para acesso aos dados.
  • SQL Engine (DB.Engine): coordena Parser → Planner → Executor, gerencia transações e tratamento de erros.
  • CLI (DB.CLI): interface REPL para interação do usuário, envio de comandos e exibição de resultados.

Cada camada se comunica apenas com as adjacentes, facilitando testes unitários e evolução de funcionalidades. No próximo tópico, veremos como inicializar o projeto e estruturar cada módulo antes de codificar.

2. Setup Inicial do Projeto

  1. Crie o projeto supervisionado: mix new mini_db --sup
  2. Adicione ao mix.exs: defp deps do [ {:nimble_parsec, "~> 1.0"} ] end
  3. Estrutura de pastas em:
  4. Ajuste o application.ex para supervisionar os componentes necessários.

Próximos Passos

Na Parte 2, começaremos pela implementação do DB.Storage, definindo o formato de página e as funções de leitura/escrita.


Referências

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *