
PostgreSQL o MySQL: el ganador cambia cuando predominan lecturas o escrituras

Si predominan las lecturas simples e indexadas, MySQL puede ser la elección más conveniente cuando el equipo ya lo opera bien y cumple la latencia exigida. Si pesan las escrituras concurrentes, las transacciones con varias operaciones o las consultas complejas, PostgreSQL merece prioridad en la evaluación. Son criterios para elegir qué probar primero, no una clasificación universal de velocidad.
La mezcla de operaciones cambia qué motor encaja mejor: una aplicación que consulta fichas por clave plantea un problema distinto de otra que actualiza inventario mientras confirma pedidos. Para decidir, hay que medir esas operaciones completas bajo la concurrencia prevista y mantener iguales los requisitos de consistencia. Un resultado aislado de transacciones por segundo puede orientar la investigación, pero no sustituye esa carga.
Qué revela un benchmark en el mismo servidor
En una prueba de Nube Colectiva, PostgreSQL 17 con pgbench registró 6116,96 transacciones por segundo y MySQL 8 con sysbench registró 780,60, ejecutados por separado en el mismo VPS de 4 vCPU y 8 GB, con unos cinco millones de filas, 20 clientes y 60 segundos por prueba. La diferencia describe esas configuraciones y esas herramientas; no mide una misma transacción de aplicación ejecutada por ambos motores.
El límite está en la unidad que se cuenta. pgbench y sysbench oltp_read_write incluyen sentencias y cantidades de trabajo diferentes dentro de cada transacción. Dividir sus cifras de TPS produciría una ventaja aparente, pero no diría cuánto tarda cada motor en completar, por ejemplo, la misma compra con sus lecturas, cambios y confirmación. Tampoco basta con pasar a consultas por segundo: una búsqueda indexada y una actualización que modifica varios índices tienen costes distintos.
Lecturas frecuentes: importan el acceso y la visibilidad
Una carga dominada por consultas de registros conocidos favorece una decisión pragmática: conservar MySQL puede tener sentido si sus tiempos de respuesta ya cumplen el objetivo y el equipo domina su operación. Esa conclusión depende del servicio concreto, no de atribuir a MySQL una superioridad general en lecturas. El tamaño de los datos activos, los índices utilizados y el número de consultas simultáneas pueden cambiar el resultado incluso sin modificar la proporción de lecturas.
La consistencia forma parte de la prueba. Una pantalla que debe mostrar inmediatamente un cambio recién confirmado exige una ruta de lectura distinta de una pantalla que tolera datos retrasados. También importa si una transacción debe mantener una vista estable mientras hace varias consultas o si puede observar cambios entre ellas. Comparar tiempos después de cambiar el nivel de aislamiento o la ruta de lectura equivale a comparar comportamientos diferentes.
Conviene separar las consultas baratas de las que filtran grandes conjuntos, ordenan resultados o combinan tablas. Aunque todas sean lecturas, pueden necesitar índices y memoria muy distintos. Si las consultas más frecuentes son sencillas pero una búsqueda compleja determina la experiencia del usuario, su latencia debe figurar por separado en el resultado.
Escrituras concurrentes: dónde aparece el coste
Cuando muchas solicitudes insertan o actualizan datos a la vez, el promedio de consultas oculta las esperas que más afectan al servicio. Hay que distinguir escrituras repartidas entre claves independientes de escrituras que compiten por la misma fila, como un saldo o una existencia disponible. En el segundo caso, el conflicto puede limitar el rendimiento aunque sobren CPU y memoria.
La explicación de concurrencia de PostgreSQL describe cómo su control multiversión permite que las lecturas ordinarias y las escrituras avancen sin bloquearse mutuamente. Eso ayuda a entender su comportamiento, pero no elimina la competencia entre transacciones que modifican los mismos datos. Para juzgar una operación de escritura hay que incluir sus restricciones, índices, lecturas previas y confirmación, además de contar los intentos que terminan en error o requieren repetirse.
PostgreSQL merece una prueba temprana si el producto depende de transacciones con varias tablas o de consultas complejas que acompañan a las actualizaciones. La ventaja real, si aparece, debe verse en la transacción completa y en los tiempos de las solicitudes lentas. Medir solo inserciones aisladas dejaría fuera precisamente el trabajo que motivó la elección.
JSON modifica tanto las lecturas como las escrituras
Los dos motores pueden almacenar JSON, pero la consulta concreta y su índice determinan el coste. La documentación de tipos JSON de PostgreSQL describe jsonb como un formato procesable que admite índices, a cambio de trabajo al convertir los datos de entrada. El manual de JSON de MySQL explica que el tipo nativo permite buscar y modificar valores, y que para indexar un valor extraído puede emplearse una columna generada.
Por eso, contar documentos almacenados dice poco sobre el rendimiento de una función que filtra por un campo interno. La prueba debe ejecutar ese filtro con el índice que usaría la aplicación y registrar también el coste de mantenerlo cuando cambian los documentos. Si varias transacciones actualizan con frecuencia una misma fila que contiene JSON, el patrón de conflicto merece una medición propia; no se deduce del tiempo de lectura.
Réplicas y capacidad del equipo
Enviar lecturas a réplicas puede aliviar al servidor que recibe las escrituras, pero introduce retraso en la visibilidad de los cambios. La documentación de replicación de MySQL indica que su replicación es asíncrona por defecto y que las réplicas pueden atender lecturas mientras el servidor de origen recibe las actualizaciones. Si una solicitud lee justo después de escribir, dirigir esa lectura a una réplica puede devolver un estado anterior.
La topología debe evaluarse como parte del sistema que recibirá tráfico, no como capacidad gratuita añadida al servidor principal. Hay que definir qué operaciones admiten retraso y cuáles deben leer del origen, y medir la latencia de cada ruta. Una configuración que reparte muy bien las consultas puede ser inadecuada para una función que exige ver de inmediato el cambio confirmado.
La experiencia del equipo también tiene un coste medible en la operación: diagnosticar consultas lentas, restaurar copias, ajustar índices y atender incidentes requiere conocimiento del motor elegido. Si PostgreSQL y MySQL satisfacen los mismos objetivos de latencia y consistencia, la capacidad de sostener la configuración probada puede decidir la elección sin atribuir una victoria de rendimiento que la prueba no mostró.
Árbol de decisión para una aplicación concreta
- Si predominan lecturas simples e indexadas y MySQL ya cumple los objetivos del servicio, mantenlo como candidato principal y comprueba su latencia con la concurrencia prevista.
- Si predominan escrituras simultáneas, transacciones de varias operaciones o consultas complejas, prueba PostgreSQL pronto y observa conflictos, errores y tiempos de confirmación.
- Si JSON interviene en rutas críticas, compara los filtros y cambios reales con los índices necesarios en cada motor.
- Si habrá réplicas, decide primero qué lecturas toleran retraso; después mide la topología completa y la ruta de lectura tras una escritura.
- Si ambos cumplen los requisitos, incorpora el coste de migración y la experiencia operativa del equipo a la decisión.
Plantilla para repetir el benchmark
Parte de una mezcla tomada de la aplicación: búsquedas por clave, filtros, inserciones, actualizaciones y transacciones completas, con una frecuencia aproximada para cada operación. Usa el mismo volumen y distribución de datos, la misma infraestructura y un esquema lógico equivalente. Anota los índices, el nivel de aislamiento, las versiones y los ajustes de cada motor; los valores de fábrica y una configuración afinada responden a preguntas diferentes.
Ejecuta la misma secuencia funcional contra ambos motores y aumenta la concurrencia por etapas. Registra operaciones completadas, errores, latencia habitual y latencia de los casos lentos, además de CPU, memoria y esperas. Si la aplicación usa réplicas, registra su retraso y separa las lecturas que llegan al origen de las que llegan a ellas. El punto en que la latencia deja de cumplir el objetivo puede ser más útil para elegir que el máximo de TPS.
Lee también:
Artículos relacionados


DuckDB o SQLite: la consulta analítica decide antes que el archivo

Redis o Memcached: más funciones pueden perder frente a más hilos

Supabase o Firebase: trabajar sin conexión puede decidir la elección

Keenable capta 26 millones: buscar para agentes exige indexar 100.000 millones de páginas

Cloudera lleva la IA hasta los datos que no pueden ir a la nube
Suscríbete a nuestro boletín
Reciba las últimas noticias sobre Web3, IA y criptomonedas directamente en su bandeja de entrada.