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.
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.
Resumen
- La normalización elimina datos redundantes y duplicados para prevenir contradicciones; la desnormalización reintroduce redundancia controlada para reducir el trabajo en tiempo de lectura.
- Por qué Importa: Elegir el punto incorrecto en este espectro para una tabla determinada produce anomalías de actualización (sobredesnormalizada) o un coste de
JOINinnecesario (sobrernormalizada) a escala de producción. - Conceptos Clave: forma normal, anomalía de actualización, dependencia funcional, vista materializada, ratio lectura/escritura.
- Cuándo Usar: Cualquier decisión de diseño de esquema sobre si un atributo pertenece a su propia tabla o se duplica en una tabla leída frecuentemente.
- Limitaciones / Compensaciones: La normalización cuesta
JOINs en tiempo de lectura; la desnormalización cuesta trabajo de consistencia en tiempo de escritura. - Temas Relacionados: dependencias funcionales, vistas materializadas, forma de la carga de trabajo de lectura/escritura, diseño OLTP vs OLAP.
Fundamentos
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".
Mecánicas e Interacciones
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.
Consideraciones Avanzadas y Aplicaciones
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.
Conceptos Erróneos Comunes
- "Desnormalizar significa renunciar a la normalización." La mayoría de los sistemas desnormalizados mantienen una fuente de verdad normalizada y derivan una copia desnormalizada de ella, en lugar de abandonar la normalización por completo.
- "3NF es siempre el objetivo correcto." 3NF es un valor predeterminado razonable para tablas OLTP, pero algunos diseños se detienen antes o van más allá (BCNF) dependiendo de qué anomalías amenacen realmente el dominio.
- "Las vistas materializadas siempre están actualizadas." Una vista materializada solo refleja el estado en su último
REFRESH, y PostgreSQL no la refresca automáticamente a menos que algo esté programado o activado para hacerlo. - "Los
JOINs son siempre lentos, así que desnormaliza proactivamente." UnJOINbien 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 desnormalización estilo OLAP también funciona bien para tablas OLTP." La duplicación estilo esquema en estrella está ajustada para datos de análisis pesados en lectura y escritos por lotes, y aplicarla a una tabla transaccional de alta concurrencia generalmente solo reubica las anomalías de actualización en lugar de evitarlas.
Preguntas Frecuentes
¿Cuál es la diferencia principal entre normalización y desnormalización?
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.
¿Siempre debo normalizar primero y desnormalizar después si es necesario?
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.
¿Qué es una dependencia funcional y por qué es importante aquí?
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.
¿Cómo encaja una vista materializada en esta compensación?
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.
¿Cuán obsoleta puede llegar a ser una vista materializada?
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.
¿Es la desnormalización siempre sobre rendimiento?
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.
¿Cómo decido si una tabla debe ser normalizada o desnormalizada?
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.
¿Cuál es el mayor riesgo de desnormalizar una columna?
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.
¿Los sistemas OLTP y OLAP utilizan la misma estrategia de normalización?
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.
¿Es 3NF la forma normal más alta a la que debo aspirar?
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.
¿Pueden coexistir la normalización y la desnormalización en el mismo esquema?
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.
¿Qué debo comprobar antes de desnormalizar una columna?
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.
Relacionados
- Fundamentos de Normalización - ejemplos prácticos de descomposición y dependencias funcionales
- 3NF y BCNF - las formas normales formales en detalle
- Vistas Materializadas - desnormalización estructurada con un mecanismo de refresco
- Desnormalización Intencionada - cuándo y cómo romper la normalización deliberadamente
- Fundamentos de Modelado de Datos - el proceso de modelado conceptual a físico en el que esto encaja
- Modelado Entidad-Relación - las formas de relación en las que se basa la normalización
Versiones de Stack: Esta página fue escrita para PostgreSQL 18.4 (estable 18, mantenimiento 17).