Normalización frente a Desnormalización
La normalización y la desnormalización suelen presentarse como opuestas, pero responden a la misma pregunta subyacente desde diferentes direcciones: cuánta redundancia debería tolerar este esquema.
Busca en todas las páginas de la documentación
La normalización y la desnormalización suelen presentarse como opuestas, pero responden a la misma pregunta subyacente desde diferentes direcciones: cuánta redundancia debería tolerar este esquema.
La normalización elimina la redundancia para proteger la corrección; la desnormalización reintroduce parte de ella, a propósito, para hacer más rápidas ciertas lecturas específicas.
Esta página explica el razonamiento detrás de ambas, para que las páginas restantes de esta sección sobre formas normales, vistas materializadas y desnormalización intencionada se lean como herramientas en un espectro en lugar de como campos competidores.
JOIN innecesario (sobrernormalizada) a escala de producción.JOINs en tiempo de lectura; la desnormalización cuesta trabajo de consistencia en tiempo de escritura.La normalización es el proceso de organizar columnas y tablas de modo que cada hecho se almacene en un solo lugar.
Está impulsada por dependencias funcionales: si un valor como nombre_producto está completamente determinado por sku, entonces nombre_producto pertenece a la tabla con clave sku, no copiado en cada fila que hace referencia a ese producto.
Las formas normales formales (1NF, 2NF, 3NF y posteriores) son puntos de control con nombre a lo largo de este proceso, cada una cerrando una categoría específica de redundancia.
La recompensa de la normalización es que una anomalía de actualización se vuelve estructuralmente imposible: un hecho almacenado en un lugar no puede dejar de estar sincronizado consigo mismo.
La desnormalización viola deliberadamente este principio almacenando un valor derivado o duplicado en un lugar donde no era estrictamente necesario, a cambio de evitar un JOIN en tiempo de lectura.
Las dos técnicas no son etapas de madurez, donde la normalización es "correcta" y la desnormalización es un recurso de último momento; son una compensación genuina entre garantías de corrección en tiempo de escritura y coste en tiempo de lectura.
-- Normalizado: order_items no tiene datos de producto duplicados
SELECT oi.order_id, p.name, p.sku
FROM order_items oi
JOIN products p ON p.product_id = oi.product_id;La mayoría de los esquemas de producción no son puramente uno u otro; normalizan el núcleo del dominio con muchas escrituras y desnormalizan un pequeño número de rutas de lectura específicas y conocidas como "hot paths".
La decisión de dónde situarse en este espectro debe seguir el ratio lectura/escritura real de una tabla, no una preferencia general.
Una tabla escrita una vez y leída miles de veces por escritura es un fuerte candidato para cierta desnormalización, porque el coste de mantener sincronizado un valor duplicado se paga raramente en comparación con la frecuencia con la que el atajo da sus frutos.
Una tabla escrita y leída a tasas similares gana poco con la desnormalización, porque el coste de sincronización y el beneficio de evitar JOINs se cancelan aproximadamente.
PostgreSQL te ofrece una vista materializada como forma estructurada de desnormalizar sin abandonar las tablas normalizadas como fuente de verdad.
CREATE MATERIALIZED VIEW order_totals AS
SELECT order_id, SUM(amount) AS total
FROM order_items
GROUP BY order_id;
-- Refrescada explícitamente, no en cada escritura subyacente
REFRESH MATERIALIZED VIEW order_totals;La vista materializada contiene una forma precalculada y desnormalizada, pero las tablas normalizadas subyacentes siguen siendo la fuente de verdad de la que se refresca la vista.
Ese paso de refresco es el quid de cada decisión de desnormalización: alguien tiene que decidir cuán obsolec-ta puede permitirse que sea la copia desnormalizada, y qué mecanismo (un trigger, un trabajo programado, una escritura a nivel de aplicación) la mantiene dentro de ese límite.
Una columna desnormalizada sin una ruta de refresco definida no es una optimización de rendimiento, es un error de corrección que se acumula lentamente.
A escala, el argumento del ratio lectura/escritura se extiende a la distinción OLTP versus OLAP que da forma al diseño de todo un sistema, no solo de una tabla.
Las cargas de trabajo OLTP (muchas transacciones pequeñas, fuertes necesidades de consistencia) tienden a ser normalizadas, porque la corrección bajo escrituras concurrentes importa más que recortar un JOIN de un informe raro.
Las cargas de trabajo OLAP (grandes consultas agregadas sobre datos históricos) tienden a ser desnormalizadas, a menudo en tablas de hechos y dimensiones de estilo "star schema", porque los datos se escriben una vez mediante un proceso por lotes y se leen repetidamente por analistas.
La desnormalización intencionada en un sistema OLTP, hecha correctamente, es estrecha y documentada: una columna específica, una consulta "hot" específica, un mecanismo de consistencia específico declarado, en lugar de una política general de duplicar datos dondequiera que parezca conveniente.
| Enfoque | Fortaleza | Debilidad | Mejor Ajuste |
|---|---|---|---|
| Normalización completa (3NF+) | Sin anomalías de actualización; fuente única de verdad por hecho | Las rutas de lectura pueden requerir varios JOINs | Tablas OLTP con escrituras frecuentes y concurrentes |
| Vista materializada | Velocidad de lectura desnormalizada con una fuente de verdad normalizada intacta | Los datos pueden estar obsoletos entre refrescos | Agregados costosos leídos mucho más a menudo de lo que cambia la fuente |
| Columna desnormalizada ad hoc | Lectura más rápida posible para esa única columna | Requiere un mecanismo de sincronización explícito; fácil de olvidar | Una ruta "hot" única y probada con un propietario claro |
| Esquema en estrella (hecho/dimensión) | Optimizado para escaneos de agregados grandes | Mal ajuste para escrituras transaccionales de alta concurrencia | Cargas de trabajo OLAP y de informes |
El modo de fallo honesto en este espectro no es elegir la desnormalización, es elegirla silenciosamente, sin escribir la tolerancia a la obsolescencia o el mecanismo de refresco en ningún lugar donde un futuro ingeniero pueda encontrarlo.
REFRESH, y PostgreSQL no la refresca automáticamente a menos que algo esté programado o activado para hacerlo.JOINs son siempre lentos, así que desnormaliza proactivamente." Un JOIN bien indexado en un esquema normalizado es frecuentemente lo suficientemente rápido, y la desnormalización prematura añade riesgo de sincronización para un problema de rendimiento que puede que aún no exista.La normalización almacena cada hecho en un solo lugar para prevenir contradicciones entre copias duplicadas.
La desnormalización duplica o precalcula datos deliberadamente para evitar el coste de JOIN de volver a ensamblarlos en tiempo de lectura.
Sí, ese es el orden predeterminado más seguro: normaliza para establecer una fuente de verdad correcta, luego desnormaliza rutas específicas y probadas como "hot paths" una vez que tengas evidencia de que las necesitas.
Desnormalizar especulativamente, antes de que exista un patrón de lectura real, añade riesgo sin un beneficio correspondiente.
Una dependencia funcional A -> B significa que el valor de A determina completamente el valor de B.
La normalización utiliza dependencias funcionales para decidir en qué tabla debe ir un atributo: si sku determina nombre_producto, ese nombre pertenece al SKU, no duplicado en cada fila que lo referencia.
Una vista materializada almacena un resultado precalculado y desnormalizado, mientras que las tablas normalizadas subyacentes siguen siendo la fuente de verdad real.
Te da velocidad en tiempo de lectura sin descartar la corrección en tiempo de escritura, a costa de que la vista esté obsoleta hasta que se refresque.
Tan obsoleta como el tiempo entre las llamadas a REFRESH MATERIALIZED VIEW, ya que PostgreSQL no la refresca automáticamente ante escrituras subyacentes.
La ventana de obsolescencia aceptable es una decisión que el equipo debe tomar explícitamente, no una propiedad que PostgreSQL te imponga.
En esta sección, sí: la razón para desnormalizar es casi siempre evitar el coste de JOIN en una ruta específica y leída frecuentemente.
Otras razones a veces citadas, como la conveniencia, suelen ser una señal de que la desnormalización no fue lo suficientemente deliberada.
Observa su ratio lectura/escritura real: una tabla leída mucho más a menudo de lo que se escribe es un candidato razonable para cierta desnormalización.
Una tabla leída y escrita a tasas similares generalmente gana poco con ella.
Hacerlo sin un mecanismo definido para mantener sincronizado el valor duplicado con su fuente.
Una columna desnormalizada no sincronizada deriva silenciosamente a datos incorrectos con el tiempo.
No: los sistemas OLTP generalmente tienden a ser normalizados porque la corrección de escrituras concurrentes es lo más importante, mientras que los sistemas OLAP tienden a ser desnormalizados, a menudo en esquemas en estrella, porque los datos se escriben en lotes y se leen repetidamente para análisis.
3NF elimina las categorías de anomalías que importan para la mayoría de los esquemas de aplicaciones, y BCNF cierra un caso límite más estrecho que involucra claves candidatas superpuestas.
La mayoría de los equipos apuntan a 3NF por defecto y recurren a BCNF solo cuando ese caso límite específico está presente.
Sí, y en la práctica casi siempre lo hacen: la mayoría de los esquemas de producción normalizan sus tablas principales con muchas escrituras, mientras desnormalizan un pequeño número de rutas de lectura "hot" conocidas y medidas.
Tratar la elección como si fuera para todo el esquema en lugar de por tabla suele ser un error.
Confirma que el ratio lectura/escritura realmente lo justifica, y anota el mecanismo de refresco o consistencia antes de enviar el cambio.
Una desnormalización sin un plan de obsolescencia declarado es un error esperando a manifestarse, no una optimización terminada.
Versiones de Stack: Esta página fue escrita para PostgreSQL 18.4 (estable 18, mantenimiento 17).
Revisado por Chris St. John·Última actualización: 15 jul 2026