Motores de bases de datos: cuál elegir y por qué
Hasta ahora has aprendido SQL usando SQLite. Pero SQL no pertenece a un solo motor: es un lenguaje estándar que implementan muchos sistemas diferentes. Elegir el motor adecuado para tu proyecto es una de las decisiones más importantes que tomarás como desarrollador.
¿Qué es un motor de base de datos?
Un motor (o sistema gestor) de base de datos es el software que se encarga de almacenar, organizar y permitir el acceso a los datos. Cuando escribes una consulta SQL, es el motor quien la interpreta, la optimiza y la ejecuta.
Los motores más relevantes en el mundo relacional son:
SQLite: la base de datos más usada del mundo
Esto no es exageración. SQLite está en todas partes. Cada teléfono Android, cada iPhone, cada navegador web (Chrome, Firefox, Safari), cada sistema macOS y Windows la incluyen. Se estima que hay más de un billón de instancias activas de SQLite en el mundo.
¿Por qué? Porque SQLite es embebida: no necesita un servidor. La base de datos es un solo archivo .db que tu aplicación lee y escribe directamente. No hay que instalar nada, no hay que configurar usuarios ni puertos.
-- Con SQLite, abrir una base de datos es tan simple como
-- indicar la ruta al archivo. No hay conexión a un servidor.
.open mi_aplicacion.dbCuándo usar SQLite:
- Aplicaciones móviles (Android, iOS)
- Aplicaciones de escritorio (Electron, Tauri)
- Prototipos y desarrollo local
- Sitios web con poco tráfico concurrente
- Datos embebidos en dispositivos IoT
- Tests y desarrollo
Cuándo NO usar SQLite:
- Aplicaciones web con muchos usuarios escribiendo a la vez
- Cuando necesites acceso remoto a la base de datos
- Sistemas con alta concurrencia de escritura
Su licencia es dominio público: ni siquiera es open source, es algo aún más libre. No hay ninguna restricción de uso, copia, modificación ni distribución. Puedes hacer lo que quieras con SQLite.
app.js app.js La historia de MySQL: de open source a Oracle
MySQL fue durante años la base de datos del desarrollo web. La famosa pila LAMP (Linux, Apache, MySQL, PHP) construyó gran parte de la web que conocemos: WordPress, Facebook en sus inicios, YouTube…
MySQL fue creada en 1995 por la empresa sueca MySQL AB bajo licencia GPL. En 2008, Sun Microsystems la compró por 1.000 millones de dólares. Solo un año después, Oracle compró Sun Microsystems y, con ella, MySQL.
Esto fue problemático. Oracle es la empresa detrás de Oracle Database, el mayor competidor comercial de MySQL. Muchos desarrolladores temieron (con razón) que Oracle descuidaría MySQL o limitaría su naturaleza open source.
Y eso es exactamente lo que sucedió de forma progresiva:
- Oracle cerró el acceso a los tests de calidad del código.
- Algunas funcionalidades avanzadas quedaron solo en la versión de pago (MySQL Enterprise).
- El desarrollo comunitario se volvió opaco: las decisiones las toma Oracle, no la comunidad.
- Se añadió una licencia dual: GPL para uso open source, pero licencia comercial obligatoria si no quieres distribuir tu código como GPL.
MySQL sigue siendo funcional y ampliamente usada, pero ya no es la opción de confianza que fue. Su desarrollo está controlado por una corporación cuyo negocio principal es vender bases de datos propietarias.
MariaDB: el fork que intentó ser el relevo
El creador original de MySQL, Michael “Monty” Widenius, vio venir los problemas con Oracle. Antes de que la adquisición se completara, creó MariaDB como un fork (bifurcación) de MySQL en 2009.
MariaDB se diseñó para ser un reemplazo directo (drop-in replacement) de MySQL: mismos comandos, mismos protocolos, misma sintaxis. Podías migrar de MySQL a MariaDB sin cambiar una línea de código.
Su licencia es GPL v2 pura, sin licencia comercial dual. La gobernanza es a través de la MariaDB Foundation, una organización sin ánimo de lucro.
MariaDB añadió funcionalidades que MySQL no tenía:
- Motores de almacenamiento adicionales (Aria, ColumnStore)
- Mejor rendimiento en ciertos escenarios
- Funciones de ventana antes que MySQL
- Versionado temporal de tablas
Sin embargo, con los años MariaDB y MySQL han ido divergiendo. Ya no son 100% compatibles, y MariaDB ha tenido sus propios problemas empresariales (su empresa comercial casi quiebra en 2023).
PostgreSQL: el motor que se ganó a los desarrolladores
Mientras MySQL y MariaDB debatían sobre licencias y forks, PostgreSQL fue ganando terreno silenciosamente hasta convertirse en la base de datos relacional más admirada por los desarrolladores según la encuesta de Stack Overflow.
PostgreSQL nació en la Universidad de Berkeley en 1986 como proyecto académico (entonces llamado POSTGRES). Su enfoque siempre fue la corrección y el cumplimiento de estándares SQL.
¿Por qué PostgreSQL ha tomado la delantera?
- Licencia PostgreSQL: una de las más permisivas que existen. Similar a MIT/BSD. Puedes hacer lo que quieras, incluso crear productos comerciales basados en PostgreSQL sin obligación de abrir tu código. No hay trampa ni versión “enterprise” restringida.
- Tipos de datos avanzados: JSON/JSONB nativo, arrays, hstore, tipos geoespaciales con PostGIS, rangos, tipos personalizados…
- Extensibilidad: puedes crear tus propios tipos de datos, operadores, funciones en múltiples lenguajes (PL/pgSQL, Python, JavaScript…).
- Integridad de datos impecable: soporte completo de transacciones ACID, constraints avanzados, triggers sofisticados.
- Ecosistema moderno: herramientas como Supabase, Neon, o Vercel Postgres han hecho que PostgreSQL sea la opción por defecto en el desarrollo moderno.
Diferencias importantes de sintaxis
Aunque todos estos motores hablan “SQL”, hay diferencias significativas. Aquí van algunas de las más importantes:
Autoincremento
-- SQLite
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
-- PostgreSQL
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT
);
-- O en PostgreSQL moderno:
CREATE TABLE users (
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name TEXT
);
-- MySQL / MariaDB
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
);Tipos de texto
| Motor | Tipo principal | ¿Tiene límite? |
|---|---|---|
| SQLite | TEXT | No (dinámico) |
| PostgreSQL | TEXT / VARCHAR(n) | TEXT es ilimitado |
| MySQL | VARCHAR(n) / TEXT | VARCHAR requiere longitud máxima |
SQLite es especial aquí: usa tipado dinámico. Puedes almacenar cualquier valor en cualquier columna, independientemente del tipo declarado. Los demás motores son estrictos con los tipos.
Booleanos
-- SQLite: no tiene tipo BOOLEAN nativo, usa 0 y 1
SELECT * FROM users WHERE active = 1;
-- PostgreSQL: tiene BOOLEAN nativo
SELECT * FROM users WHERE active = TRUE;
-- MySQL: BOOLEAN es un alias de TINYINT(1)
SELECT * FROM users WHERE active = TRUE; -- TRUE es 1Concatenar texto
-- SQLite y PostgreSQL
SELECT name || ' ' || surname FROM users;
-- MySQL / MariaDB
SELECT CONCAT(name, ' ', surname) FROM users;UPSERT (insertar o actualizar)
-- SQLite
INSERT INTO users (id, name) VALUES (1, 'Ana')
ON CONFLICT(id) DO UPDATE SET name = excluded.name;
-- PostgreSQL
INSERT INTO users (id, name) VALUES (1, 'Ana')
ON CONFLICT(id) DO UPDATE SET name = EXCLUDED.name;
-- MySQL / MariaDB
INSERT INTO users (id, name) VALUES (1, 'Ana')
ON DUPLICATE KEY UPDATE name = VALUES(name);Limitar resultados
-- SQLite, PostgreSQL y MySQL
SELECT * FROM users LIMIT 10;
-- PostgreSQL también soporta el estándar SQL:
SELECT * FROM users FETCH FIRST 10 ROWS ONLY;JSON
-- SQLite (soporte básico)
SELECT json_extract(data, '$.name') FROM config;
-- PostgreSQL (soporte avanzado con JSONB)
SELECT data->>'name' FROM config;
SELECT * FROM config WHERE data @> '{"active": true}';
-- MySQL (soporte intermedio)
SELECT JSON_EXTRACT(data, '$.name') FROM config;
-- O con el atajo:
SELECT data->>"$.name" FROM config;PostgreSQL tiene la ventaja clara aquí: su tipo JSONB almacena JSON en formato binario, permite índices sobre campos JSON y tiene operadores específicos (@>, ?, #>) que lo hacen extremadamente potente.
Cuándo usar cada motor
| Escenario | Motor recomendado | Por qué |
|---|---|---|
| App móvil / escritorio | SQLite | Embebido, sin servidor, un solo archivo |
| App web moderna | PostgreSQL | Robusto, extensible, gran ecosistema |
| Proyecto legacy LAMP | MariaDB | Compatible con MySQL, licencia limpia |
| Microservicio simple | SQLite | Mínima infraestructura |
| Datos geoespaciales | PostgreSQL + PostGIS | El estándar de la industria |
| Analítica / data warehouse | PostgreSQL | Funciones de ventana, CTEs recursivos, JSONB |
| Empezar un proyecto nuevo | PostgreSQL | La opción más versátil y con mejor futuro |
Resumen de licencias
Este es un punto crítico que muchos desarrolladores ignoran:
- SQLite — Dominio público. Sin restricciones de ningún tipo.
- PostgreSQL — Licencia PostgreSQL (tipo MIT/BSD). Puedes hacer lo que quieras, incluso productos comerciales cerrados.
- MariaDB — GPL v2. Si distribuyes software que incluye MariaDB, debes publicar el código fuente (o comprar licencia comercial).
- MySQL — GPL v2 + Licencia comercial de Oracle. Mismo requisito que MariaDB, pero si no quieres cumplir GPL, debes pagar a Oracle.
En la práctica, si usas la base de datos como servicio (tu app se conecta a un servidor de base de datos), la GPL generalmente no te obliga a liberar tu código. Pero si embedes el motor dentro de tu software y lo distribuyes, sí.
PostgreSQL y SQLite ganan aquí por goleada: cero preocupaciones legales.
Prueba las diferencias
El playground de este curso usa SQLite. Prueba algunas de las peculiaridades que has aprendido:
Nuestras tablas
| id | name | type | license | year |
|---|---|---|---|---|
| 1 | SQLite | Embebido | Dominio público | 2000 |
| 2 | PostgreSQL | Cliente-servidor | PostgreSQL (MIT-like) | 1996 |
| 3 | MariaDB | Cliente-servidor | GPL v2 | 2009 |
| 4 | MySQL | Cliente-servidor | GPL v2 / Comercial | 1995 |
| 5 | Oracle DB | Cliente-servidor | Comercial | 1979 |
| 6 | SQL Server | Cliente-servidor | Comercial | 1989 |
| id | engine_id | feature | supported |
|---|---|---|---|
| 1 | 1 | JSON nativo | 1 |
| 2 | 1 | Tipado dinámico | 1 |
| 3 | 1 | Sin servidor | 1 |
| 4 | 1 | Funciones de ventana | 1 |
| 5 | 2 | JSON/JSONB | 1 |
| 6 | 2 | Tipos personalizados | 1 |
| 7 | 2 | Extensiones (PostGIS) | 1 |
| … | … | … | … |
| 15 | 4 | Funciones de ventana | 1 |