Ir al contenido

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.

5 min de lectura

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.

Preguntas relacionadas

¿Laravel favorece a uno de los dos?
En realidad no. Los dos son de primera clase en el framework, los dos están cubiertos por el constructor de consultas y el de esquemas, y contra los dos se prueba Laravel. Donde el framework se inclina es en los valores por defecto, no en el soporte, y un valor por defecto no es una recomendación para su carga.
¿Podemos cambiar después?
El esquema y las migraciones se mueven con un esfuerzo moderado. Lo que no se mueve barato es todo lo que usó una funcionalidad que solo tiene uno de los dos, y todo aquello donde su código se apoyó en una diferencia de comportamiento sin nombrarla: el orden con mayúsculas y minúsculas mezcladas es el caso clásico. Presupueste la migración de datos y las consultas de informes, no el ORM.
¿Cuál es más rápido?
Para las consultas que ejecuta una aplicación de negocio típica, la diferencia es mucho menor que la que marca un índice que falta. Los dos le servirán mucho más allá del punto en que el cuello de botella sea su esquema. Elegir por benchmarks es optimizar la variable equivocada.
¿Y MariaDB?
Está lo bastante cerca de MySQL para casi todo en Laravel y ha divergido en algunos puntos, entre ellos el tratamiento de JSON y parte de la sintaxis más reciente. Trátelo como un objetivo propio en lugar de asumir paridad, y fije contra cuál corre su CI.

← Volver a todos los artículos

Llamar+1 848 272 7583WhatsApp+90 850 308 5436Correoinfo@codefacture.comPágina de contacto