¿SQLite en producción?

Read in English.

He usado las bases de datos por un tiempo: dBase III, QuickSilver y Clipper en los años 80, DB/2 (la mitad de una base de datos como la llamaba en broma en ese entonces), SQL Server (más tarde MSSQL), Oracle, Paradox, FoxPro, rBase y Lotus Notes como base de datos en los años 90, MS Access (con MDE) y de vuelta a MSSQL, y de nuevo a DB2 en z/OS y ​​luego ingresé a la era de NoSQL con MongoDB, SQLite para pruebas locales, Redis (una base de datos no relacional en memoria) y de regreso a SQL con MySQL. Incluso escribí mi propio motor de base de datos compatible con dBase III en C++ (con ingeniería reversa completa del formato de índice de árbol y el sistema de bloqueo de archivos para escritura) y tengo una patente sobre el uso de bases de datos para registrar y depurar aplicaciones.

Entonces, ¿he oído hablar de SQLite? Claro, es un pequeño motor de base de datos de un solo archivo que se puede usar para aplicaciones móviles o para ejecutar algunas pruebas unitarias en tu máquina local y es tan flexible que se puede activar una base de datos durante las pruebas unitarias del CI y destruirla al final. También se puede configurar como una instancia local de la base de datos, para no tener que estar conectado mientras se desarrolla la aplicación. Pero espera, ¿realmente crees que también se puede usar en producción? ¿Como la base de datos de mi preciosa aplicación? ¿Con redundancia? ¿Y buen rendimiento? ¿Y DR (Recuperación de desastres, por sus siglas en Inglés)?

DevOps

Bueno, sí, eso es exactamente lo que estoy diciendo. A lo largo de los años hemos creado una abstracción en torno a las bases de datos que oculta parte de su complejidad. Nosotros “solicitamos” bases de datos y esperamos que alguien más se encargue del almacenamiento, los derechos, las copias de seguridad, el ajuste del rendimiento, la escala, el crecimiento, etc., pero ¿no va eso en la dirección opuesta a DevOps? En la disciplina DevOps, queremos que todos los componentes de nuestra aplicación estén bajo nuestro control (DevOps). Entonces, para lograr DevOps de bases de datos, deberíamos automatizar el aprovisionamiento de las bases de datos administradas o tal vez podríamos repensar nuestra postura sobre las bases de datos.

DBA

Históricamente, las bases de datos necesitaban ajustes del rendimiento, y eso era una ciencia en sí misma, por lo que contratamos a un grupo de expertos y los llamamos DBA (Administradores de Bases de Datos, por sus siglas en Inglés). A lo largo de los años, esa agradable separación también hizo posible arrojar más y más cosas por encima del muro al DBA, para que los desarrolladores de “aplicaciones” pudieran concentrarse en desarrollar la funcionalidad de la aplicación. Pero, este mundo en el que el desarrollador no necesitaba preocuparse por los problemas de la base de datos, también se convirtió en un problema en sí mismo, porque ahora los desarrolladores querían usar estos sencillos servicios de bases de datos para todo, incluso para cosas que realmente no pertenecen a las bases de datos administradas, esperando que los administradores de bases de datos resuelvan los problemas y el rendimiento.

Como con la mayoría de las cosas, el equilibrio adecuado es aprender a elegir la herramienta adecuada para cada trabajo. Y, sí, hay muy buenas razones para solicitar una base de datos administrada, pero una gran cantidad de aplicaciones no consideran las calificaciones, solo solicitan una base de datos administrada por conveniencia. Cuando el vendedor de televisores pregunta qué estamos buscando, la respuesta casi siempre se expresa en los límites superiores de tamaño y dinero, y lo mismo ocurre con las bases de datos, por supuesto, nos gustaría lo mejor que podamos obtener en iops y velocidades de transferencia, y la cantidad máxima de columnas, cuando, en realidad, la mayoría de esos números harán muy poca o ninguna diferencia en el rendimiento de nuestra aplicación.

La optimización del rendimiento

¿Por qué necesitamos ajustar el rendimiento de un query? Obviamente, porque no está funcionando bien, ¿no? Bueno, se sorprenderá cuántas veces he visto a los desarrolladores (e incluso a mí mismo) sobredimensionar el ajuste del rendimiento de alguna consulta antes de haber considerado cuánto afectará a la aplicación en ejecución. Hoy en día, hay muchas formas de mejorar el rendimiento de una consulta, como comprar hardware más rápido, usar caché o usar co-habitación; cualquiera de esos mecanismos podría resolver el problema de rendimiento, pero arreglarlo antes de que sepamos que es un problema no es un buen uso de nuestro tiempo. Tenga en cuenta que no dije que no deberíamos pensar mucho en crear esquemas sólidos, un buen índice podría hacer una gran diferencia; solo estoy señalando que no es la única herramienta en nuestro maletín.

Almacenamiento en caché

Hablando de herramientas, las bases de datos de pares clave-valor en memoria, como redis y etcd, deben usarse para el almacenamiento en caché en lugar de su base de datos principal. Esas herramientas ya vienen preoptimizadas para ese propósito y no deberíamos reinventar esa rueda tratando de hacerlo en nuestra base de datos solamente porque es posible.

Autogestionado

Aunque hay muchas y muy buenas razones para elegir una base de datos administrada, no es nuestra única opción y, en un número creciente de casos, en mi opinión, no es la mejor opción. ¿Por qué optar por bases de datos autogestionadas?

  • Ciclo vital. La base de datos se crea, se actualiza, se mejora y se da de baja con la aplicación. La aplicación de parches del sistema operativo (que hoy en día se llama reconstruir el contenedor), las actualizaciones de la versión de la base de datos y todas las demás razones de rutina para coordinar con los DBA ahora están totalmente bajo el control del equipo de la aplicación y se pueden sincronizar con el ciclo vital de la aplicación.
  • Autonomía. La aplicación ahora no solo es independiente de otras aplicaciones que no pueden actualizar las bases de datos a la misma velocidad, sino que también se puede mover la aplicación a otras ubicaciones/mejores/más flexibles (en las instalaciones o en diferentes nubes) sin tener que preocuparse por las rutas entre la nueva ubicación de la aplicación y la antigua ubicación de la base de datos.
  • Tráfico en red. La ventaja de compartir la ubicación de la base de datos con el servidor de aplicaciones no es solo la autonomía, sino que además podría producir una mejora del rendimiento al hacer que los paquetes de datos viajen por una ruta más corta, lo que ahora daría la libertad de realizar múltiples llamadas a la base de datos sin la necesidad urgente de crear una llamada SQL enorme pero potencialmente ineficiente para obtener todos los datos de una sola vez.

Pero, ¿SQLite?

Es una base de datos de juguete, ¿no? No, no es. Es un sistema de base de datos completa que se ha utilizado para aplicaciones en producción durante muchos años. Varias de las aplicaciones que ejecutas todos los días en tu celular probablemente estén almacenando todos sus datos en SQLite. Ha estado allí, ha demostrado su estabilidad y confiabilidad, lo único que está cambiando es la percepción anterior de que solo debe usarse como una base de datos integrada para una herramienta o aplicación móvil a una nueva apreciación de esta herramienta madura como una potencial base de datos para un mayor porcentaje de aplicaciones.

Compatibilidad

SQLite implementa todas las características comunes de SQL con muy pocas excepciones, como “RIGHT OUTER JOIN”, pero, para ser honesto, mis aplicaciones han sobrevivido la última década sin ellas. Por supuesto, no había estado considerando SQLite como una alternativa de producción seria para la mayoría de mis aplicaciones hasta hace poco, pero he estado usando SQLite para la mayor parte de mis pruebas unitarias y locales, lo que demuestra que tiene todas las características que REALMENTE ESTOY USANDO de las alternativas más grandes.

Sencillez

Si has estado desarrollando aplicaciones con el apoyo de DBAs, probablemente no hayas estado consciente de la complejidad del sistema de base de datos. Incluso si ya te convenció la cultura DevOps y comenzaste a implementar y actualizar tu base de datos desde tu código, probablemente te hayas asegurado de que permanezca separada de tu aplicación, a través de contenedores, y es posible que no hayas prestado mucha atención a los objetos persistentes del sistema de base de datos. Pero sería difícil ignorar la simplicidad del sistema SQLite, ya que la única forma de usarlo es pasar el nombre del archivo a SQLite, e inmediatamente notarás que toda la base de datos está contenida en este único archivo. ¿Significa eso que hay limitaciones físicas? Puedes leer sobre las limitaciones aquí, pero probablemente nos topemos con las limitaciones de nuestra potencia computacional antes de acercarnos a algunos de esos límites. Pero no se puede exagerar la simplicidad de la base de datos de un solo archivo. La copia de seguridad, la migración y la transferencia de datos se simplifican con el enfoque de un solo archivo.

Portabilidad

Esta podría ser la razón más importante para darle a SQLite una segunda mirada como base de datos de producción. ¿No sería maravilloso tener tus datos exactamente en el mismo formato, independientemente de dónde se esté ejecutando tu aplicación? La base de datos relacional tradicional funciona bien en una o dos de las plataformas principales, pero no lo pondrías en tu teléfono celular o electrodomésticos… lo contrario solía ser cierto también, SQLite funciona extremadamente bien en tu teléfono celular, televisores y electrodomésticos pero no lo uses como la base central de tu aplicación web, pero ahora, eso está cambiando. El mismo motor y el mismo formato de archivo no solo están disponibles, sino que son portátiles en todos los dispositivos en los que podría pensar en necesitar una base de datos.

Nivel de Empresa

Hay algunas utilidades que se están presentando para complementar la simplicidad de SQLite con características que solo se esperaría de una solución de nivel “Empresarial”. DqLite , por ejemplo, ” (SQLite distribuido) extiende SQLite a través de un grupo de máquinas, con conmutación por error automática y alta disponibilidad para mantener tu aplicación funcionando“. Además, el muy prometedor LiteStream , “ejecuta tu aplicación de manera segura en un solo servidor. Base de datos completamente replicada sin problemas y con un costo mínimo.” Y, acabo de escuchar de LiteFS, que “es un sistema de archivos basado en FUSE para replicar bases de datos SQLite a lo largo de un cluster de computadoras“. Todas estas iniciativas ayudan a responder a las necesidades de un sistema distribuido, la disponibilidad y copias de seguridad de una solución empresarial.

Recordando las aplicaciones que he desarrollado (o a las que he contribuido) durante los últimos 10 años que requerían una base de datos para almacenar sus propios datos, y excluyendo las que requerían acceso a bases de datos externas, encontré que SQLite podría haber sido extremadamente apropiada para el gran mayoría de ellos. En realidad, podría cambiar varios de ellos muy fácilmente ya que 1) ya fueron probadas con SQLite durante su desarrollo y 2) normalmente uso Sequelize (un ORM para NodeJS) y mi propio easy-sequelize (enchufe desvergonzado) que abstrae la selección del motor de su consumo.

Oportunidad

¿Deberíamos todos cambiar nuestras bases de datos de producción a SQLite? Por supuesto que no, esa no es la intención de este artículo, ni por asomo. Pero esta lista podría ayudarte a decidir:

  • Servidor-cliente. SQLite no tiene un componente de servidor, si la arquitectura de tu aplicación requiere que la aplicación cliente envíe consultas SQL a un motor de servidor para su procesamiento, SQLite no es tu respuesta.
  • Multiusuario. Si tu escenario requiere que varios clientes lean y escriban la base de datos al mismo tiempo, SQLite no es tu mejor opción, aunque durante casi dos décadas me he alejado lentamente de tales implementaciones y he creado una interfaz para los datos (API) donde los múltiples clientes no usan SQL, sino REST APIs, y luego la implementación de la API es el único usuario de la base de datos. La mayoría de las veces, el uso de un API brinda una mejor arquitectura, independientemente de usar SQLite o una RDBMS tradicional en la parte trasera, pero reconozco que hay buenos casos de uso para lo contrario.
  • Concurrencia. Si tu aplicación necesita una gran cantidad de clientes que accedan a la base de datos al mismo tiempo, SQLite no es tu mejor opción. Lo mismo es cierto para grandes volúmenes o enorme cantidades de datos, en esos casos debería preferirse los RDBMS altamente optimizados que fueron diseñaron para esos escenarios.

Conclusión

Como de costumbre, no hay una respuesta única para este tipo de dilema, y ​​siempre se debe elegir la herramienta más adecuada para el trabajo. Pero es importante saber que, si has estado usando SQLite para tus pruebas unitarias y te encanta su simplicidad, cada vez se abren más oportunidades, incluida la posibilidad de usar SQLite como la única base de datos para tu aplicación en producción.