PostgreSQL y MySQL son las dos bases de datos relacionales open source más usadas del mundo. MySQL domina en aplicaciones web, PostgreSQL en sistemas empresariales y científicos. ¿Cuándo elegir uno sobre el otro?
Historia y filosofía
MySQL nació en 1995 pensando en velocidad y simplicidad. Fue la elección natural para el stack LAMP y la web de los 2000s. Hoy pertenece a Oracle pero MariaDB (su fork) sigue siendo 100% comunitario.
PostgreSQL nació en la Universidad de Berkeley en 1986 con un foco diferente: cumplimiento estricto del estándar SQL, soporte completo de ACID y extensibilidad. Es el sistema de base de datos más avanzado que existe en el mundo open source.
Diferencias técnicas clave
| Característica | MySQL / MariaDB | PostgreSQL |
|---|---|---|
| Cumplimiento SQL | Parcial | Muy alto |
| Tipos de datos | Estándar | JSON nativo, arrays, hstore, rangos, geoespacial |
| Índices | B-tree, Full-text | B-tree, Hash, GiST, SP-GiST, GIN, BRIN |
| JSON | Básico (MySQL 5.7+) | JSONB con índices GIN, muy eficiente |
| Window Functions | MySQL 8.0+ | Completo y maduro |
| CTEs (WITH) | MySQL 8.0+ | Completo |
| Extensiones | Limitadas | PostGIS (geo), pgVector (IA), TimescaleDB |
PostgreSQL: funciones que MySQL no tiene (o llegaron tarde)
-- JSONB con índice (extremadamente eficiente)
CREATE TABLE eventos (
id SERIAL PRIMARY KEY,
datos JSONB NOT NULL,
timestamp TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_eventos_datos ON eventos USING GIN(datos);
-- Buscar dentro del JSON con índice
SELECT * FROM eventos WHERE datos @> '{"tipo": "login", "exitoso": true}';
-- Arrays nativos
CREATE TABLE articulos (
id SERIAL PRIMARY KEY,
titulo TEXT NOT NULL,
tags TEXT[] NOT NULL DEFAULT '{}'
);
INSERT INTO articulos (titulo, tags)
VALUES ('Docker básico', ARRAY['docker', 'contenedores', 'devops']);
SELECT * FROM articulos WHERE 'docker' = ANY(tags);
-- Window Functions (análisis avanzado)
SELECT
titulo,
vistas,
RANK() OVER (PARTITION BY categoria_slug ORDER BY vistas DESC) AS ranking_en_categoria
FROM articulos;
Conectar PostgreSQL con PHP
PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
// Los prepared statements funcionan igual
$stmt = $pdo->prepare('SELECT * FROM articulos WHERE categoria_slug = $1 LIMIT $2');
// Nota: PostgreSQL usa $1, $2... en lugar de ? para los placeholders
$stmt->execute(['redes', 10]);
¿Cuándo elegir cada uno?
Elige MySQL/MariaDB cuando: tu equipo ya lo conoce · el proyecto es una aplicación web estándar (blog, CMS, e-commerce) · necesitas compatibilidad con hosting compartido · priorizas la simplicidad de administración
Elige PostgreSQL cuando: necesitas tipos de datos avanzados (JSON, arrays, geoespacial) · tienes queries analíticas complejas con window functions y CTEs · vas a usar extensiones como PostGIS o pgVector para IA · el cumplimiento estricto de ACID es crítico · necesitas escalar a terabytes de datos
"MySQL te lleva del punto A al punto B. PostgreSQL te lleva ahí también, y de paso puede hacer 20 cosas más que no sabías que necesitabas."