Menu

SQLite vs MySQL: ¿qué base de datos elegir?

Diferencias reales entre SQLite y MySQL: arquitectura, concurrencia, tipos de datos y para qué tipo de proyecto está pensada cada una.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Dos formas distintas de entender una base de datos

SQLite y MySQL hablan SQL y guardan filas en tablas, pero la manera en que encajan dentro de un sistema es completamente distinta. SQLite es una biblioteca: tu aplicación se enlaza contra ella y lee directamente desde un fichero en disco. MySQL, en cambio, es un servidor: un proceso aparte al que te conectas mediante un socket o por red.

Esa única diferencia condiciona todo lo demás: cómo se instalan, cuántos procesos pueden escribir a la vez, cómo se hacen las copias de seguridad y cómo se despliegan. La mayoría de las dudas sobre SQLite vs MySQL son, en el fondo, dudas sobre bases de datos embebidas frente a cliente-servidor.

-- SQLite: abre un archivo y ya tienes una base de datos.
sqlite3 app.db

-- MySQL: conéctate a un servidor en ejecución.
mysql -h localhost -u root -p

El comando de SQLite abre (o crea) un archivo. El de MySQL, en cambio, abre una conexión contra un proceso que ya tiene que estar corriendo, configurado y aceptando logins.

Arquitectura: embebida vs cliente-servidor

En una aplicación con SQLite, el motor de la base de datos corre dentro de tu propio programa. No hay puerto, ni demonio, ni systemctl start. Una llamada a la librería sqlite3 lee y escribe páginas directamente sobre un archivo en disco.

MySQL funciona al revés. El servidor mysqld guarda los datos, gestiona las conexiones, aplica los permisos, ejecuta el planificador de consultas y se encarga del bloqueo. Tu aplicación es un cliente que manda cadenas SQL por la red y recibe filas como respuesta.

Las consecuencias prácticas:

  • Despliegue. SQLite viaja con tu aplicación: un binario, un archivo. MySQL exige instalar, asegurar, monitorizar y respaldar un servidor aparte.
  • Acceso por red. MySQL expone un puerto, así que varios servidores de aplicación pueden conectarse a la misma base de datos. SQLite asume un único proceso (o unos pocos cooperando) en la misma máquina.
  • Permisos. MySQL tiene usuarios, roles y sentencias GRANT. El único sistema de permisos de SQLite son los permisos del sistema operativo sobre el archivo de la base de datos.

Ninguno de los dos modelos es "mejor". Resuelven problemas distintos.

Concurrencia y escrituras

Aquí es donde de verdad se separan los caminos. El motor InnoDB de MySQL hace bloqueo a nivel de fila: muchas conexiones pueden escribir en filas distintas al mismo tiempo sin pisarse.

SQLite, en cambio, serializa las escrituras a nivel de base de datos. Un único escritor a la vez, sin excepciones. Los lectores sí pueden trabajar en paralelo con el escritor (sobre todo en modo WAL), pero un segundo escritor tiene que esperar su turno.

-- SQLite: esto funciona bien para muchos lectores y un escritor a la vez.
PRAGMA journal_mode = WAL;

-- MySQL: muchos escritores, bloqueo de grano fino.
-- (Sin configuración especial — InnoDB lo hace por defecto.)

Para una app con uno o dos procesos haciendo escrituras moderadas —una herramienta de escritorio, una app móvil, un CMS pequeño— las escrituras serializadas de SQLite suelen ser lo bastante rápidas como para que ni te enteres. Pero en un servicio web con mucho tráfico y cientos de conexiones insertando pedidos o actualizando sesiones, el bloqueo a nivel de fila de MySQL marca la diferencia entre "todo va bien" y "todo está haciendo cola detrás de un único lock".

Tipos de datos en SQLite vs MySQL

MySQL maneja una lista larga y estricta de tipos: TINYINT, INT, BIGINT, VARCHAR(n), DATETIME, DECIMAL(p,s), BLOB, JSON y muchos más. Si declaras una columna como INT, MySQL rechazará cualquier cadena que intentes meter ahí.

SQLite, en cambio, funciona con afinidad de tipos. Los tipos de columna son sugerencias, no reglas que se hagan cumplir. Puedes guardar una cadena en una columna INTEGER y SQLite la almacenará sin chistar (a menos que actives las tablas STRICT, disponibles desde la versión 3.37).

Las dos filas se insertan sin problema. Esa flexibilidad es cómoda cuando estás prototipando, pero choca cuando esperas que la base de datos te valide los tipos. Si quieres un comportamiento estricto al estilo MySQL dentro de SQLite, usa tablas STRICT.

Diferencias de sintaxis con las que te vas a topar

La mayor parte del SQL básico —SELECT, JOIN, WHERE, GROUP BY— es idéntico en ambos. Las diferencias entre SQLite y MySQL se concentran en unos pocos puntos:

  • Claves primarias autoincrementales. En SQLite se usa INTEGER PRIMARY KEY (que ya autoincrementa por defecto). En MySQL es INT AUTO_INCREMENT PRIMARY KEY.
  • Comillas en identificadores. MySQL admite comillas invertidas para identificadores (`table`). SQLite usa comillas dobles ("table"), siguiendo el estándar SQL.
  • Funciones de fecha. MySQL trae NOW(), CURDATE(), DATE_ADD(). En SQLite tienes datetime('now'), date('now'), datetime('now', '+1 day').
  • Sintaxis de LIMIT. Las dos soportan LIMIT n OFFSET m, así que aquí no hay sorpresas.
  • Booleanos. MySQL tiene BOOLEAN (que en realidad es un alias de TINYINT(1)). SQLite guarda los booleanos como 0 y 1 en columnas INTEGER.
-- MySQL
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at DATETIME DEFAULT NOW()
);

-- SQLite
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    created_at TEXT DEFAULT (datetime('now'))
);

La intención es la misma, solo cambian las palabras clave. El modelo mental se mantiene; la sintaxis pide algún ajuste menor.

Rendimiento: depende de la pregunta

"¿SQLite es más rápido que MySQL?" no tiene una única respuesta.

Cuando hablamos de un solo proceso leyendo y escribiendo en local, SQLite suele ganar: no hay salto por red, ni comunicación entre procesos, ni un parser de consultas corriendo en otro espacio de memoria. En la práctica, un SELECT en SQLite es prácticamente una llamada a función.

En cambio, con muchas conexiones concurrentes escribiendo sobre la misma base de datos, MySQL toma ventaja gracias a su bloqueo a nivel de fila. El modelo de un único escritor de SQLite hace que la contención aparezca rapidísimo bajo esa carga.

Para cargas con muchas lecturas y el modo WAL activado, SQLite escala sorprendentemente bien: los lectores no se bloquean entre sí ni bloquean al único escritor. De hecho, hay un montón de sitios en producción sirviendo tráfico real desde SQLite.

No elijas en base a benchmarks que encuentres por ahí. Elige según tu patrón real de acceso.

Cuándo conviene cada uno

Tira de SQLite cuando:

  • La base de datos vive junto a una sola aplicación (app móvil, herramienta de escritorio, CLI, sitio web pequeño).
  • Quieres despliegue sin configuración: basta con copiar el archivo.
  • Las lecturas superan ampliamente a las escrituras, o las escrituras son poco frecuentes.
  • Necesitas una base de datos embebida para tests que refleje el SQL de producción.
  • Estás prototipando y aún no te quieres preocupar de levantar un servidor.

Tira de MySQL cuando:

  • Varios servidores de aplicación necesitan compartir una misma base de datos.
  • Tienes muchos escritores concurrentes.
  • Necesitas permisos de usuario detallados y gestión de roles.
  • Trabajas sobre un stack (LAMP, configuraciones gestionadas habituales en la nube) que espera MySQL.
  • El tooling operativo —replicación, recuperación a un punto en el tiempo, monitoreo— es un requisito innegociable.

Una regla rápida: si describirías tus necesidades de almacenamiento como "una app, un disco", probablemente SQLite te alcanza. Si más bien dirías "un servicio, con operadores detrás", ve a por MySQL (o PostgreSQL).

Migrar de SQLite a MySQL (y al revés)

Empezar con SQLite y pasarse a MySQL más adelante es un camino bastante recorrido, y un plan perfectamente válido. Los esquemas se traducen con ajustes pequeños, y los datos se exportan limpiamente con .dump desde la CLI de SQLite. Lo que más vas a tocar es la sintaxis del auto-incremento, las funciones de fechas y alguna característica propia de SQLite (índices parciales con formas raras, WITHOUT ROWID, tablas STRICT) que no tiene equivalente directo en MySQL.

El sentido contrario —de MySQL a SQLite— es menos habitual, pero también se hace, normalmente para análisis offline, copias embebidas de un subconjunto de datos o fixtures de tests.

La idea de fondo: elegir SQLite hoy no te encierra en nada. El SQL que escribes se transfiere, y lo que aprendes también.

Lo que viene: SQLite vs PostgreSQL

MySQL es la comparación más habitual, pero PostgreSQL es la otra base de datos contra la que verás enfrentado a SQLite, y ahí las diferencias son distintas otra vez. Eso lo vemos en la siguiente página.

Preguntas frecuentes

¿Cuál es la diferencia principal entre SQLite y MySQL?

SQLite es una base de datos embebida: un único archivo que tu aplicación lee y escribe directamente, sin ningún proceso servidor de por medio. MySQL, en cambio, es cliente-servidor: hay un proceso mysqld aparte escuchando en un puerto, y tu aplicación se comunica con él por red. Esa diferencia de arquitectura es la que condiciona prácticamente todos los demás tradeoffs entre ambas.

¿SQLite es más rápido que MySQL?

Para un único proceso haciendo lecturas y escrituras pequeñas, sí: SQLite se ahorra el viaje por red y la comunicación entre procesos, así que suele ir más rápido. Cuando tienes muchos escritores concurrentes, gana MySQL sin discusión, porque SQLite serializa las escrituras a nivel de base de datos. La respuesta real depende de tu carga de trabajo, no de los motores en abstracto.

¿Cuándo conviene usar SQLite en lugar de MySQL?

SQLite encaja en aplicaciones embebidas, móvil, herramientas de escritorio, utilidades de línea de comandos, cachés locales, tests y webs pequeñas o medianas con un solo servidor de aplicación. Tira de MySQL cuando necesites varios servidores de aplicación atacando una misma base de datos, permisos de usuario detallados o una carga de escrituras lo bastante alta como para que importe el bloqueo a nivel de fila.

¿Puedo migrar de SQLite a MySQL más adelante?

Sí, y es un camino bastante habitual. Los dialectos SQL coinciden en lo esencial para CREATE TABLE, INSERT y SELECT, pero tendrás que ajustar tipos (INTEGER PRIMARY KEY pasa a ser INT AUTO_INCREMENT), funciones de fecha y cualquier característica específica de SQLite como WITHOUT ROWID o los índices únicos parciales. Herramientas como pgloader o un script de volcado a medida se encargan de la mayor parte del trabajo.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR