Del modelo ER al esquema de base de datos
La normalización tiene fama de académica, y se la ganó por enseñarse como cinco reglas numeradas en vez de como una sola pregunta repetida: ¿este hecho pertenece aquí?
11 min de lecturaER - crow's foot3 de 3
La respuesta corta
- La tercera forma normal en una frase: toda columna no clave depende de la clave, de toda la clave y de nada más que la clave.
- Una clave subrogada sobrevive a que el negocio cambie de idea sobre qué identifica algo, cosa que acaba pasando.
- Desnormaliza solo después de medir el camino de lectura. Antes de la medida cambias una garantía de corrección por una ganancia sin confirmar.
- Pasar de ER a SQL es mecánico: entidad a tabla, uno-a-muchos a clave ajena en el lado de muchos, muchos-a-muchos a tabla propia.
01La tabla por la que empieza todo el mundo#
Esto no es un espantapájaros: es la forma que tiene una hoja de cálculo, y en una hoja de cálculo empiezan la mayoría de los esquemas. Vale la pena ser preciso sobre qué falla, porque "no está normalizada" no explica nada:
Lo que sigue es modelado de esquemas de bases de datos en el sentido corriente de la expresión: decidir cuáles son las tablas, qué columna identifica cada fila y dónde se le permite vivir a un hecho. Es el paso entre un diagrama ER y un DDL que una base aceptará, y conviene darlo sobre papel, porque cada una de estas decisiones sale cara de deshacer una vez que hay datos en la tabla.
- No puedes guardar un cliente que no ha pedido nada. El cliente solo existe como columnas de un pedido.
- Corregir un correo obliga a actualizar todas las filas donde aparece ese cliente - y saltarse una deja a la base sosteniendo dos respuestas distintas.
- Borrar el último pedido borra al cliente. La información desaparece como efecto colateral de algo que no tiene que ver.
product_namescontiene una lista. A partir de ahora toda consulta que necesite un producto analiza una cadena, y ningún índice puede ayudar.totalpuede contradecir a las líneas de las que se supone que es la suma.
Esos cinco tienen nombre - anomalías de inserción, de actualización y de borrado, un grupo repetido y un valor derivado - y la normalización no es más que el procedimiento que los elimina.
02Elige primero las claves#
Todo lo demás depende de esto, así que va antes que las tablas. Una clave primaria debe ser única, nunca nula y no cambiar jamás. La tercera condición es la que descarta a la mayoría de los candidatos.
| Elemento | Notación | Qué significa |
|---|---|---|
| Clave subrogada | bigint o uuid | Generada, sin significado, estable para siempre. La opción por defecto. Un entero secuencial es compacto y amable con los índices; un UUID lo puede generar el cliente y no filtra volúmenes. |
| Clave natural | ISBN, IBAN, código de país | Con significado, y segura solo cuando un organismo de normalización garantiza que no cambiará. De verdad califica una lista corta. |
| Clave compuesta | dos columnas o más | La adecuada para tablas de unión, donde el par de claves ajenas es la identidad y a la vez la restricción de unicidad que querías de todos modos. |
| Clave de negocio | número de pedido, SKU | Pensada para personas, debe ser única y debería ser una restricción UNIQUE en lugar de la clave primaria, para poder corregirse cuando aparezca una errata en ella. |
03La normalización, en tres pasos#
Hay seis formas normales y necesitas tres. Cada una es una sola pregunta sobre una tabla, y la respuesta "no" te dice qué columna mover adónde.
| Elemento | Notación | Qué significa |
|---|---|---|
| Primera forma normal | sin grupos repetidos | Cada columna contiene un valor. Nada de listas separadas por comas, nada de product_1 / product_2 / product_3. La parte que se repite se va a su propia tabla. |
| Segunda forma normal | sin dependencias parciales | Cada columna no clave depende de la clave entera. Solo es un problema con claves compuestas: el nombre de un producto en una tabla (order_id, product_id) depende de media clave, así que pertenece a products. |
| Tercera forma normal | sin dependencias transitivas | Ninguna columna no clave depende de otra columna no clave. Un customer_email en un pedido depende del cliente, no del pedido. Muévelo a customers. |
El viejo resumen sigue siendo el mejor: toda columna no clave depende de la clave, de toda la clave y de nada más que la clave.
Pasa la tabla plana por las tres. La 1FN parte product_names y quantities en una tabla order_lines, una fila por producto. La 2FN nota que el nombre y el precio de un producto dependen solo del producto, así que aparece products. La 3FN nota que el nombre y el correo del cliente dependen del cliente y no del pedido, así que aparece customers. Cuatro tablas, que son justo el diagrama de cabecera - y ningún paso pidió criterio, solo la pregunta.
04Valores derivados y desnormalización#
La columna total de la tabla plana es un problema distinto de los otros cuatro: no está mal colocada, está duplicada. Se puede calcular a partir de las líneas del pedido, así que puede contradecirlas, y acabará haciéndolo.
Tres respuestas legítimas, por orden de preferencia: calcularla en la consulta; calcularla en una vista; guardarla y dejar que la base la mantenga - una columna generada, una vista materializada o un disparador. Lo que no es legítimo es guardarla y confiar en que el código de la aplicación se acuerde de actualizarla; esa es la versión que produce facturas que no cuadran.
Úsalo cuando
- Un patrón de lectura medido es demasiado lento y la reunión es demostrablemente la causa
- El valor es una instantánea, no una derivación: el precio en el momento del pedido
- Una tabla de informes alimentada por una tarea programada, nombrada claramente como tal
- La base puede mantener la copia por sí misma, así que no puede desviarse
Usa otra cosa cuando
- Podría ser lento más adelante: mide primero, y normalmente no lo es
- El código de la aplicación tiene que acordarse de mantener la copia al día
- El duplicado es además la fuente de verdad de otra cosa
- Estás desnormalizando el esquema transaccional para servir a un panel
05Modelar la herencia#
Un modelo ER sabe expresar un supertipo con subtipos; una base relacional no tiene esa construcción, así que el modelo físico debe elegir uno de tres diseños. Los tres se usan mucho y la elección es un compromiso real.
| Elemento | Notación | Qué significa |
|---|---|---|
| Tabla única | una tabla, una columna de tipo | Las columnas de todos los subtipos en una tabla, la mayoría nulas. Consultas simples, sin reuniones - y la base no puede imponer "un pago con cheque debe llevar código de sucursal". |
| Tabla por subtipo | una tabla cada uno, clave compartida | Una tabla padre con las columnas comunes y una tabla hija por subtipo, atada a ella por la clave. Las restricciones funcionan de verdad; toda consulta se reúne. |
| Tabla por tipo concreto | tablas totalmente separadas | Ninguna tabla compartida. Rápido y limpio dentro de cada subtipo - y consultar "todos los pagos" exige una unión que crece con cada subtipo añadido. |
Regla aproximada: pocos subtipos con columnas casi todas comunes favorecen la tabla única; muchos subtipos con columnas divergentes y restricciones reales favorecen la tabla por subtipo; y los subtipos que nunca se consultan juntos favorecen tablas separadas. El diagrama de clases del mismo dominio habrá elegido su herencia sin enfrentarse a nada de esto, y por eso los dos modelos tienen permiso para diferir aquí.
06Llegar al DDL#
Un modelo ER lógico se traduce a DDL casi mecánicamente, que es la recompensa por haberlo dibujado bien:
| Elemento | Notación | Qué significa |
|---|---|---|
| Entidad | CREATE TABLE | Una tabla. Nombre de tabla en plural, nombre de entidad en singular: elige una convención y mantenla. |
| Clave primaria | PRIMARY KEY | Implica not null y unique, y crea el índice. |
| Relación | REFERENCES | Una clave ajena en el lado de muchos. El índice añádelo tú: la mayoría de las bases no crean uno para una clave ajena, y su ausencia hace que los borrados se arrastren. |
| Extremo obligatorio | NOT NULL | La barra interior de la pata de gallo es exactamente esta restricción. |
| Uno a uno | UNIQUE en la clave ajena | Si no, es un uno a muchos que de momento solo tiene una fila. |
| Entidad de unión | PRIMARY KEY compuesta | Las dos claves ajenas juntas. Es lo que impide registrar dos veces el mismo par. |
Dos cosas que el diagrama no te dice y que el DDL debe decidir: qué pasa al borrar (CASCADE para una relación identificadora, RESTRICT para casi todo lo demás), y qué columnas reciben índices más allá de las claves. Ambas son decisiones sobre comportamiento y carga, no sobre el modelo, y ambas conviene anotarlas junto al esquema en lugar de descubrirlas después en un registro de consultas lentas.
07Errores comunes#
- Normalizar más allá de lo útil. La 3FN es el destino de un esquema transaccional. Partir una tabla porque una columna podría repetirse algún día no aporta nada y cuesta una reunión para siempre.
- Sin claves ajenas, "por rendimiento". El coste es una búsqueda en índice al escribir; el beneficio es que las filas huérfanas se vuelven imposibles. Casi nunca es el intercambio correcto.
- Columnas anulables haciendo de tabla ausente. Seis columnas que solo se rellenan para un tipo de fila son un subtipo pidiendo su propia tabla.
statuscomo texto libre. Restríngelo - con una restricción de comprobación, un enumerado o una tabla de referencia - o en un año contendráshipped,ShippedySHIPPED.- Marcas de tiempo sin zona horaria. Correctas exactamente una vez, en una oficina, hasta que el primer servidor se mude.
- El diagrama abandonado tras la primera migración. Un diagrama de esquema que contradice a la base es peor que ninguno, porque la gente se fía de él.
Si los símbolos de cardinalidad de los diagramas de arriba necesitan descifrarse, están cubiertos en la notación pata de gallo; la forma del modelo en sí está en los diagramas ER.
En una línea cada uno
- 01Elige las claves antes que las tablas: únicas, no nulas y que no cambien nunca.
- 02Toda columna no clave depende de la clave, de toda la clave y de nada más que la clave.
- 03La 1FN parte grupos repetidos, la 2FN arregla claves parciales, la 3FN mueve hechos mal colocados.
- 04Desnormaliza sobre una medición, y solo donde la base mantenga la copia.
- 05Un precio histórico no es un duplicado: es un hecho distinto.
- 06La pata de gallo se traduce a DDL casi mecánicamente; indexa tus claves ajenas.
08Preguntas frecuentes#
¿Qué es la tercera forma normal?
Una tabla está en tercera forma normal cuando toda columna no clave depende de la clave, de toda la clave y de nada más que la clave. En la práctica: sin grupos repetidos, sin columnas que dependan solo de parte de una clave compuesta, y sin columnas que dependan de otra columna no clave.
¿Qué diferencia hay entre una clave subrogada y una natural?
Una clave natural son datos que ya identifican la fila, como un ISBN. Una subrogada es un valor generado sin significado, como un entero o un UUID. Las subrogadas se mantienen estables cuando el negocio cambia de idea sobre qué identifica algo, cosa que acaba pasando.
¿Cuándo se justifica la desnormalización?
Cuando has medido un camino de lectura que la normalización volvió demasiado lento, y puedes vivir con que el valor duplicado quede obsoleto. Desnormalizar antes de tener esa medida cambia una garantía de corrección por un beneficio de rendimiento cuya existencia no has confirmado.
¿Cómo se implementa la herencia en un esquema relacional?
Tres opciones: una tabla para toda la jerarquía con una columna discriminadora y muchas columnas anulables, una tabla por clase concreta con las columnas comunes repetidas, o una tabla por clase unidas por una clave compartida. Cuál es la correcta depende de con qué frecuencia consultas atravesando la jerarquía, frente a cuánto difieren las subclases.
¿Cómo se convierte un diagrama ER en SQL?
Cada entidad se vuelve una tabla, cada atributo una columna, y el atributo identificador la clave primaria. Las relaciones uno-a-muchos se vuelven una clave ajena en el lado de muchos, y las muchos-a-muchos una tabla propia. Después añade las restricciones not null y unique que implican las cardinalidades del diagrama.
En esta serie
- 01Diagramas ER
- 02Notación pata de gallo
- 03Diseño de esquema
Lecturas relacionadas
Fundamentos
Referencia de notación
Diagramas de estructura
Diagramas de estructura