MySQL o Postgres para Laravel: qué difiere de verdad
Eloquent esconde casi toda la distancia entre los dos, y luego un puñado de funcionalidades no viaja. Cuáles son, y cuáles de ellas notaría al cabo de un año.
Eloquent esconde la diferencia lo bastante bien como para que la mayoría de los equipos elija por costumbre y nunca sepa qué eligió. Eso suele estar bien. Deja de estarlo en cuatro puntos concretos, y los cuatro llegan mucho después de la decisión.
Dónde son genuinamente iguales
En todo lo que hacen casi todas las aplicaciones. select, insert, joins,
transacciones, índices, claves foráneas, el constructor de consultas, el de
esquemas, migraciones, factories y todos los tipos de relación de Eloquent. Si
la aplicación es CRUD sobre un esquema relacional, no notará una diferencia
durante mucho tiempo.
Así que el planteamiento honesto no es "cuál es mejor". Es: cuál de las cuatro divergencias de abajo va a alcanzar de verdad su aplicación.
1. JSON, donde Postgres va por delante y sí importa
Los dos guardan JSON. Solo uno indexa bien rutas arbitrarias dentro de él.
$table->json('settings');En Postgres quiere jsonb en vez de json, y el método jsonb() de Laravel se
lo da. La diferencia es que jsonb se analiza y se guarda en forma binaria, de
modo que un índice GIN puede cubrirlo, y una consulta así usa un índice:
Order::where('meta->channel', 'marketplace')->get();En MySQL una columna generada más un índice sobre ella le lleva al mismo sitio para una ruta conocida, lo cual está bien cuando tiene una ruta conocida y es tedioso cuando la forma es de verdad dinámica.
Si la aplicación guarda un bloque de ajustes por inquilino, una carga útil por webhook, o cualquier cosa por la que después querrá filtrar sin saber hoy por qué clave, ese es el argumento individual más fuerte a favor de Postgres en una aplicación Laravel.
2. Mayúsculas y minúsculas, que es una trampa de comportamiento
La colación por defecto de MySQL no distingue mayúsculas. Postgres sí.
User::where('email', 'Test@example.com')->first();Eso encuentra test@example.com en MySQL y no encuentra nada en Postgres. Toda
aplicación escrita contra MySQL tiene cierto número de comparaciones que
funcionan solo por ese valor por defecto, y nadie ha escrito cuáles.
Ninguno de los dos comportamientos está mal. Lo que está mal es descubrir la diferencia durante una migración. Normalice al escribir - ponga el correo en minúsculas en un mutador, añada un índice único sobre la columna normalizada - y la pregunta deja de importar en cualquiera de los dos motores.
Lo mismo vale para el orden. ORDER BY name coloca manzana y Manzana de
forma distinta en los dos, lo que aparece en listas paginadas como registros que
salen en dos páginas o en ninguna.
3. Restricciones y tipos que Postgres tiene y MySQL no
Restricciones CHECK que comprueban de verdad. Una columna de estado limitada a cuatro valores, impuesta por la base de datos en lugar de por una form request que un trabajo en cola puede esquivar.
Índices parciales. Un índice solo sobre las filas que importan - WHERE deleted_at IS NULL en una tabla con borrado suave, o solo las suscripciones
activas. En una tabla grande con un subconjunto caliente pequeño es una
ganancia grande y MySQL no tiene equivalente.
Tipos array y rango reales, y extensiones. Si hay algo geográfico, PostGIS es la razón por la que la decisión ya está tomada.
INSERT ... RETURNING, que Laravel expone y que significa que una
inserción que necesita de vuelta la fila generada es un viaje de ida y vuelta
en lugar de dos.
4. Las diferencias operativas, que son las que le despiertan
Cambios de esquema. Los dos pueden bloquear. Postgres añade una columna
anulable al instante y construye un índice con CONCURRENTLY - que Laravel no
emite, así que lo escribe a mano, y no puede correr dentro de una transacción.
MySQL reciente resuelve la adición instantánea de columnas en muchos casos y el
DDL en línea en muchos más. Ninguno es seguro por defecto en una tabla grande,
y el modo de fallo es idéntico.
Replicación y conexiones. Las conexiones de Postgres son más caras, y por eso una aplicación Laravel con una flota grande de workers llega antes a un límite de conexiones y por eso aparece antes un pooler delante. MySQL tolera un número bruto de conexiones mayor. Esto interactúa directamente con cuántos workers de cola ejecuta.
Búsqueda de texto completo. Postgres tiene búsqueda de texto completo integrada y utilizable, con ranking. La de MySQL es más débil. Las dos son un apaño antes de un motor de búsqueda de verdad, pero el apaño dura más en Postgres.
Cómo elegir de verdad
Elija Postgres si el modelo de datos tiene JSON que va a consultar, o restricciones que quiere impuestas en lugar de confiadas, o cualquier cosa geográfica, o informes que pronto querrán funciones de ventana y CTEs.
Elija MySQL si su equipo y su alojamiento ya lo ejecutan y la aplicación es trabajo relacional directo. La familiaridad de quienes recibirán la llamada a las tres de la mañana es una entrada de ingeniería real, no una concesión.
Y elija lo que elija, fíjelo en todas partes. La versión más cara de esta decisión es un equipo desarrollando en SQLite, probando en MySQL y ejecutando Postgres en producción, descubriendo las diferencias un incidente cada vez. Su entorno local, su CI y su base de datos de producción deberían ser el mismo motor y la misma versión mayor - por razones que también aparecen en la batería de pruebas.
