3 pontos por GN⁺ 2023-08-14 | 1 comentários | Compartilhar no WhatsApp
  • O LearnDB é um sistema de gerenciamento de banco de dados relacional (RDBMS) e clone do SQLite implementado do zero para entender mais a fundo a estrutura interna de bancos de dados
  • Escrito em Python puro, não tem etapa de build e, por padrão, é zero configuração, com uma estrutura que permite sobrescrever configurações
  • Oferece o learndb-sql, com suporte a select, from, where, group by, having, limit e order by, além de um lexer e parser personalizados baseados no lark
  • É composto por um mecanismo que recebe instruções SQL e manipula as tabelas e os dados do banco, além de uma estrutura de dados de backup btree baseada em disco
  • Pode ser usado via REPL, importando como módulo Python ou passando arquivos de comandos ao mecanismo
  • A base de código é adequada para tinkering, mas tem limitações importantes que impedem seu uso como solução real de armazenamento
    • A aritmética de ponto flutuante é uma implementação bastante simplificada em comparação com IEEE754
    • Não oferece suporte a funcionalidades utilitárias comuns, como expansão de colunas por curinga em select * ...
  • Os requisitos para execução em desenvolvimento são um sistema Linux/macOS e Python 3.9 ou superior; usa fcntl para acesso exclusivo de leitura ao arquivo de banco de dados
  • Como referências, usa o tutorial de banco de dados da cstack, SQLite Database System: Design and Implementation, a documentação do formato de arquivo do SQLite e a documentação do PostgreSQL

1 comentários

 
GN⁺ 2023-08-14
Opiniões no Hacker News
  • Acho que escrever um sistema desses em uma linguagem como Python é, na verdade, uma excelente escolha. Bancos de dados normalmente são escritos em C++ ou C, mas, para mim, Python é muito mais legível e acessível
    Se a ideia for mirar seriamente em desempenho, dá para portar depois para uma linguagem de baixo nível; no formato atual, ele é útil para aprendizado
    Eu também criei em Python um banco de dados distribuído meio multimodelo, misturando SQL/grafo Cypher/documentos/estilo DynamoDB, para aprender como um motor de banco de dados pode funcionar em ambientes distribuídos: https://GitHub.com/samsquire/hash-db

    • Então acho que é por isso que existe uma comunidade de bancos de dados relacionais em Java puro. Coisas como Hypersonic, H2 e Derby; se você não precisa de escala de equipamento de grande porte, fica fácil distribuir e usar o banco de dados e, se necessário, também é fácil embuti-lo em memória
    • Concordo totalmente. Nesse sentido, a série ugit, que cria Git do zero em Python, foi realmente ótima: https://www.leshenko.net/p/ugit/
    • Não sei. Python é tão ruim quanto C/C++, e a desvantagem é que, para aprender a criar um banco de dados, há muitas partes interessantes que você deveria experimentar e que são difíceis de tocar em Python
      Tanto C quanto Python parecem acessíveis quando você ignora design ruim da linguagem, inconsistências, várias armadilhas e olha só para as partes fáceis. Mas com C pelo menos há alguma chance de aprender o jeito certo de fazer; com Python, você talvez nem chegue a saber como é o mundo real
    • Trabalho incrível. Senti algo parecido, e Python me permitiu focar nos conceitos de alto nível. Ainda assim, houve momentos no meio do caminho em que pensei que teria sido bom usar tipagem estática e uma linguagem compilada
  • Há muito tempo, alguém reescreveu/portou o SQLite de C para C#: https://code.google.com/archive/p/csharp-sqlite/wikis/Letter...
    Também vale ver o quanto o Dr. Richard Hipp recebeu bem esse trabalho
    No GitHub, provavelmente está aqui: https://github.com/CsharpDatabase/CsharpSQLite e talvez existam outros clones posteriores

  • Excelente. Com certeza deve ter sido uma experiência divertida e recompensadora
    Sei que a intenção não era fazer algo rápido, mas, por diversão, será que daria para criar alguns benchmarks?

    • Fugindo um pouco do assunto, você conhece bons materiais, palestras ou posts de blog sobre como escrever benchmarks úteis?
    • Implementar algo como TPC-C no learndb e ver no que dá também parece um exercício divertido
  • Graças a este post, descobri uma biblioteca de parser para Python chamada Lark, que parece bem boa
    O tutorial de JSON no site é excelente. Ele mostra como criar um parser básico para JSON e depois aborda, com bastante detalhe, como melhorar o desempenho: https://lark-parser.readthedocs.io/en/latest/json_tutorial.h...
    A gramática usada no projeto de RDBMS está aqui: https://github.com/spandanb/learndb-py/blob/master/learndb/l...

    • Recomendo muito o Lark para projetos Python. É fácil de usar
      Ao depurar gramáticas, a IDE foi muito útil: https://www.lark-parser.org/ide/
      No EvaDB, usamos Lark para uma linguagem semelhante a SQL voltada ao uso de modelos de IA: https://github.com/georgia-tech-db/evadb/blob/master/evadb/p... https://github.com/georgia-tech-db/evadb/
      Se você gosta do Lark, vale considerar apoiá-lo: https://github.com/sponsors/lark-parser
    • Uma DSL dentro de uma string; será que isso é mesmo uma boa abordagem? Não lembro de já ter usado isso em Python ou de ter precisado, mas fico pensando se não haveria um jeito melhor
      Só usar um dict com as chaves esperadas e composição por meio do operador OR bit a bit já não se encaixaria mais ou menos em muitas formas de gramática e seria melhor? Os imports poderiam continuar como imports, e acho que daria para misturar de alguma forma
      É só a primeira impressão de uma olhada rápida, então posso estar deixando passar alguma coisa
    • Não quero soar rude, e reconheço que este trabalho é excelente e uma forma de aprender algo novo. Mas, se a geração de parser não é o objetivo final, e sim um meio para executar a AST no banco de dados, fico curioso sobre o que se aprende apenas com a parte do parser
      Existe uma parte que precisa continuar sendo otimizada para tornar o parser gerado mais eficiente?
      O próximo passo lógico seria gerar, a partir da AST, o plano de consulta ideal?
  • Muito bom
    O SQLite é muito difícil de ler, mas esta implementação é bem fácil de entender. Especialmente a parte da máquina virtual: https://github.com/spandanb/learndb-py/blob/master/learndb/v...
    Dá para comparar com este arquivo: https://github.com/sqlite/sqlite/blob/master/src/vdbe.c
    Mas fico curioso para saber o quão completo é este LearnDB. O SQLite é difícil de ler não só porque é antigo, mas também porque lida com muitas partes do SQL e acaba ficando complexo ao seguir a especificação do SQL
    O SQLite tem uma excelente suíte de testes; seria interessante rodá-la nesta implementação

  • Muito bom mesmo, e parece uma boa forma de alguém como eu aprender melhor estruturas de dados e algoritmos. Consigo explicar como uma B+tree funciona, mas acho que travaria se me pedissem para programar uma do zero
    Gosto de bancos de dados e de Python, então foi realmente interessante dar uma olhada

    • Com certeza foi. A implementação da B-tree foi a motivação inicial para começar este projeto. Especialmente os detalhes relacionados ao rebalanceamento e à divisão de nós
      Além disso, o fato de ser uma estrutura armazenada em disco acrescentou mais uma camada de complexidade ao pensar na implementação
  • Quanto da suíte de testes do SQLite será que ele consegue passar?

  • Ele oferece suporte a garantias ACID ou a planejamento/otimização de consultas?
    Não estou perguntando no sentido de que deveria ter isso; só quero saber até onde você tentou ir além de B-tree e SQL
    Eu também gostaria de fazer algo assim algum dia. Belo trabalho

    • Sobre garantias ACID, não há o conceito de agrupar várias instruções atomicamente, ou seja, transações
      Mas, fora isso, é um banco de dados de arquivo único, e apenas uma instância do learndb pode manipular o arquivo do banco de dados. Então, por ser um banco de dados de conexão única, você obtém consistência e isolamento
      A durabilidade existe na medida em que o sistema de arquivos oferece durabilidade. Então ele fica em algum ponto dentro das propriedades ACID
      Planejamento/otimização de consultas ainda não foi implementado, mas já pensei onde um módulo de otimização poderia entrar. O parser emite uma AST, e essa AST, ou uma representação intermediária derivada dela, poderia ser otimizada
      Ou seja, antes de a VM executar a AST, ela poderia reescrever a AST ou remover nós
  • Fugindo um pouco do assunto, existe algo como mapDB em Python?
    https://mapdb.org

  • Projeto excelente. O código também é muito legível, e os comentários são ótimos