3 puntos por GN⁺ 2023-08-14 | 1 comentarios | Compartir por WhatsApp
  • LearnDB es un clon de SQLite y un sistema de gestión de bases de datos relacionales (RDBMS) implementado desde cero para comprender con mayor profundidad la estructura interna de las bases de datos
  • Está escrito en Python puro, sin etapa de build, y por defecto funciona con cero configuración, aunque permite sobrescribir la configuración
  • Ofrece learndb-sql, que soporta select, from, where, group by, having, limit y order by, junto con un lexer y parser personalizados basados en lark
  • Está compuesto por un motor que recibe sentencias SQL y manipula las tablas y los datos de la base de datos, además de una estructura de datos de respaldo basada en btree en disco
  • Se puede usar mediante REPL, importándolo como módulo de Python o pasando archivos de comandos al motor
  • La base de código es adecuada para tinkering, pero tiene limitaciones importantes por las que no debe usarse como solución de almacenamiento real
    • La aritmética de punto flotante es una implementación muy simplificada en comparación con IEEE754
    • No soporta funciones utilitarias comunes, como la expansión de columnas con comodines tipo select * ...
  • Para ejecutarlo en desarrollo se requiere un sistema Linux/macOS y Python 3.9 o superior; usa fcntl para acceso de lectura exclusivo al archivo de base de datos
  • Usa como referencias el tutorial de bases de datos de cstack, SQLite Database System: Design and Implementation, la documentación del formato de archivos de SQLite y la documentación de PostgreSQL

1 comentarios

 
GN⁺ 2023-08-14
Opiniones de Hacker News
  • Creo que escribir este tipo de sistema en un lenguaje como Python es, de hecho, una excelente elección. Las bases de datos suelen escribirse en C++ o C, pero para mí Python es mucho más fácil de leer y más accesible.
    Si se buscara rendimiento en serio, más adelante se podría portar a un lenguaje de bajo nivel, y en su forma actual es útil para aprender.
    Yo también hice en Python una especie de base de datos distribuida multimodelo, que mezcla estilos SQL/grafo Cypher/documentos/DynamoDB, para aprender cómo puede funcionar un motor de base de datos en un entorno distribuido: https://GitHub.com/samsquire/hash-db

    • Por eso parece que existe una comunidad de bases de datos relacionales en Java puro. Como Hypersonic, H2 o Derby: si no necesitas escala de equipo grande, es fácil desplegar y usar la base de datos, y también es fácil embeberla en memoria si hace falta.
    • Totalmente de acuerdo. En ese sentido, la serie ugit, que crea Git desde cero en Python, fue realmente buena: https://www.leshenko.net/p/ugit/
    • No sé. Python es tan malo como C/C++, con la desventaja de que en Python es difícil tocar muchas de las partes interesantes que deberías abordar si quieres aprender a crear una base de datos.
      Tanto C como Python parecen accesibles si ignoras el mal diseño del lenguaje, las inconsistencias y las muchas trampas, y solo miras las partes fáciles. Pero con C al menos existe la posibilidad de aprender cómo hacerlo bien, mientras que con Python puede que ni siquiera llegues a saber cómo es el mundo real.
    • Gran trabajo. Sentí algo parecido, y Python me permitió concentrarme en los conceptos de alto nivel. Dicho eso, hubo momentos en que pensé que habría sido mejor hacerlo con tipos estáticos y un lenguaje compilado.
  • Hace muchísimo tiempo, alguien reescribió/portó SQLite de C a C#: https://code.google.com/archive/p/csharp-sqlite/wikis/Letter...
    También vale la pena ver cuánto recibió con agrado ese trabajo el Dr. Richard Hipp.
    Probablemente esté aquí en GitHub: https://github.com/CsharpDatabase/CsharpSQLite, y puede que haya más clones posteriores.

  • Excelente. Seguro fue una experiencia divertida y gratificante.
    Sé que la intención no era hacerlo rápido, pero, por diversión, ¿se podrían crear también algunos benchmarks?

    • Me desvío un poco del tema, pero ¿conoces buenos recursos, charlas o posts de blog sobre cómo escribir benchmarks útiles?
    • También sería un ejercicio divertido implementar algo como TPC-C en learndb y ver qué pasa.
  • Gracias a este artículo descubrí Lark, una biblioteca de parser para Python que se ve bastante buena.
    El tutorial de JSON del sitio es excelente. Primero muestra cómo crear un parser básico para JSON y luego cubre con bastante detalle cómo mejorar el rendimiento: https://lark-parser.readthedocs.io/en/latest/json_tutorial.h...
    La gramática usada en el proyecto RDBMS está aquí: https://github.com/spandanb/learndb-py/blob/master/learndb/l...

    • Recomiendo mucho Lark para proyectos en Python. Es fácil de usar.
      El IDE fue muy útil para depurar la gramática: https://www.lark-parser.org/ide/
      En EvaDB usamos Lark para un lenguaje similar a SQL orientado al uso de modelos de IA: https://github.com/georgia-tech-db/evadb/blob/master/evadb/p... https://github.com/georgia-tech-db/evadb/
      Si te gusta Lark, vale la pena considerar patrocinarlo: https://github.com/sponsors/lark-parser
    • ¿Un DSL dentro de una cadena? ¿De verdad es una buena forma de hacerlo? No recuerdo haber usado ni necesitado esto en Python, pero me pregunto si no sería posible algo mejor.
      ¿No sería mejor usar solo dicts con claves esperadas y composición mediante el operador OR bit a bit? Eso más o menos encaja con muchas formas gramaticales. Los imports podrían quedarse como imports, y quizá se podría mezclar todo de alguna manera.
      Es mi primera impresión al verlo por encima, así que puede que se me esté escapando algo.
    • No quiero sonar grosero, y reconozco que este trabajo es excelente y que es una forma de aprender algo nuevo. Pero si generar un parser no es el objetivo final, sino un medio para ejecutar el AST en la base de datos, me pregunto qué se aprende solo con la parte del parser.
      ¿Hay partes que haya que seguir optimizando para que el parser generado sea más eficiente?
      ¿El siguiente paso lógico sería generar el plan de consulta óptimo a partir del AST?
  • Muy bueno.
    SQLite es muy difícil de leer, pero esta implementación es bastante fácil de entender. En especial la parte de la máquina virtual: https://github.com/spandanb/learndb-py/blob/master/learndb/v...
    Se puede comparar con este archivo: https://github.com/sqlite/sqlite/blob/master/src/vdbe.c
    Aunque me da curiosidad qué tan completo es LearnDB. SQLite no es difícil de leer solo porque sea antiguo, sino también porque maneja muchas partes de SQL y se vuelve complejo al seguir la especificación de SQL.
    SQLite tiene una excelente suite de pruebas, así que estaría bueno correr esas pruebas contra esta implementación.

  • Está realmente bueno y parece una buena forma para que alguien como yo aprenda mejor estructuras de datos y algoritmos. Puedo explicar cómo funciona un árbol B+, pero si me pidieran programarlo, creo que me quedaría trabado.
    Me gustan las bases de datos y Python, así que fue realmente interesante revisarlo.

    • Definitivamente lo fue. La implementación del árbol B fue la primera motivación para empezar este proyecto. En especial los detalles relacionados con el rebalanceo y la división de nodos.
      Además, el hecho de que sea una estructura almacenada en disco agregó otro factor de complejidad al pensar en la implementación.
  • ¿Cuánto de la suite de pruebas de SQLite podría pasar?

  • ¿Soporta garantías ACID o planificación/optimización de consultas?
    No lo pregunto como si tuviera que hacerlo, sino porque quiero saber hasta dónde intentaste llegar además de los árboles B y SQL.
    Yo también quisiera intentar algo así algún día. Gran trabajo.

    • En cuanto a las garantías ACID, no existe el concepto de agrupar varias sentencias de forma atómica, es decir, transacciones.
      Pero, fuera de eso, es una base de datos de un solo archivo, y solo una instancia de learndb puede ser el proceso que manipule el archivo de la base de datos. Así que, al ser una base de datos de una sola conexión, se obtiene consistencia y aislamiento.
      La durabilidad se obtiene en la medida en que el sistema de archivos la proporcione. Así que queda en algún punto dentro de las propiedades ACID.
      Todavía no implementé planificación/optimización de consultas, pero sí pensé dónde podría encajar un módulo de optimización. El parser emite un AST, y ese AST, o una representación intermedia derivada, se podría optimizar.
      Es decir, antes de que la VM ejecute el AST, se podría reescribir el AST o eliminar nodos.
  • Un poco fuera de tema, pero ¿existe algo como mapDB para Python?
    https://mapdb.org

  • Excelente proyecto. El código también es muy fácil de leer, y los comentarios son excelentes.