¿Es una mala práctica tener varias relaciones uno a uno mutuamente excluyentes?

38

Por ejemplo, una mesa cartiene relación de uno a uno a las tablas electric_car, gas_cary hybrid_car. Si a cares electric_car, ya no puede aparecer en gas_caro a hybrid_car, etc.

¿Hay algo malo con tal diseño? ¿Algunos problemas que pueden ocurrir en el futuro?

Arthur Tarasov
fuente

Respuestas:

59

Los diferentes tipos de automóviles son una instancia de un problema general que aparece una y otra vez en el modelado de datos. Se llama "generalización / especialización" en modelado ER y "superclase / subclase" en modelado de objetos.

Un modelador de objetos utiliza las características de herencia integradas en el modelo de objetos para resolver el problema con bastante facilidad. Las subclases simplemente extienden la superclase.

El modelador relacional se enfrenta a un problema. ¿Cómo diseñar las tablas para emular los beneficios que se obtendrían de la herencia?

La técnica más simple se llama herencia de tabla única . Los datos sobre todos los tipos de automóviles se agrupan en una sola tabla para automóviles. Hay una columna, car_type, que agrupa todos los autos de un solo tipo. Ningún automóvil puede pertenecer a más de un tipo. Si una columna es irrelevante para, por ejemplo, los autos eléctricos, se dejará NULL en las filas que pertenecen a los autos eléctricos.

Esta solución simple funciona bien para los casos más pequeños y más simples. La presencia de muchos NULL agrega un poquito a la sobrecarga de almacenamiento y un poco a la sobrecarga de recuperación. El desarrollador puede tener que aprender la lógica de tres valores de SQL si las pruebas booleanas se realizan en columnas anulables. Esto puede ser desconcertante al principio, pero uno se acostumbra.

Hay otra técnica, llamada herencia de tabla de clase . En este diseño, hay tablas separadas para gas_car, electric_car e hybrid_car, además de una tabla combinada, car, para todas ellas. Cuando desea todos los datos sobre un tipo específico de automóvil, une la tabla del automóvil con la tabla especializada adecuada. Hay menos NULL en este diseño, pero se unen más. Esta técnica funciona mejor en los casos más grandes y complejos.

Hay una tercera técnica llamada clave primaria compartida. Esta técnica a menudo se usa junto con la herencia de la tabla de clase. Las tablas especializadas para las subclases tienen, como clave principal, una copia de la clave principal de la entrada correspondiente en la tabla del automóvil. Se puede declarar que esta columna de identificación es la clave principal y la clave externa.

Esto implica un poco de programación adicional cuando se van a agregar autos nuevos, pero hace que las uniones sean simples, fáciles y rápidas.

Las superclases y las subclases ocurren todo el tiempo en el mundo real. No tengas miedo Pero pruebe su diseño inicial para el rendimiento. Si su primer intento es simple y sólido, podrá modificarlo para acelerarlo.

Walter Mitty
fuente
3
¡Wow gracias! Eso es lo que estaba tratando de resolver. La herencia de la tabla de clases parece ser precisamente lo que necesito. Cambié mi respuesta aceptada a esto para futuros lectores, ya que creo que cubre la pregunta por completo, no solo mi caso.
Arthur Tarasov
66
Excelente respuesta aquí. Un consejo: documente a fondo estas decisiones de diseño. Cualquiera sea la ruta que tome, no será obvio cuando alguien esté examinando la estructura de la base de datos. Algunas bases de datos como Postgres le permiten vincular un comentario junto con los metadatos de sus columnas, tablas y demás.
Basil Bourque
No abordas la restricción de evitar que los autos eléctricos también sean autos híbridos. Necesitas una mesa separada para eso.
jmoreno
2
Tienes razón. Si agrega un campo car_type a la tabla de autos, puede limitar los autos a que pertenezcan a un solo tipo, a expensas de desviarse de la normalización completa. Un buen DBMS le permitirá definir una restricción de verificación que evitará que se ingrese un automóvil en más de una tabla especializada. Hay algo de gastos generales en eso, vas a agregar autos nuevos.
Walter Mitty
@WalterMitty pero sin un car_typecampo, ¿cómo saber qué tabla buscar para obtener detalles al recuperar datos? ¿Tiene que leer las tres tablas para ver cuál tiene datos sobre ese carregistro específico ?
Josh Parte
12

No hay nada de malo en tener tantos subtipos de entidad en su modelo como sean necesarios para reflejar la realidad de los datos que está tratando de modelar. La pregunta no es si los subtipos son una mala práctica. El problema puede ser ¿es un buen modelo ?

Por ejemplo, según su ejemplo, ¿qué hace con algo como un Audi A4 eTron, que es un híbrido enchufable? ¿Es un "auto eléctrico" o es un "auto híbrido"?

La otra pregunta que debes hacerte es por qué estás subtipando. ¿Cuántos predicados distintos tienes en tus subtipos? ¿Alguno de estos predicados se comparte entre subtipos? La situación podría complicarse.

El subtipado no se usa en el diseño de bases de datos para la clasificación. Puede hacer la clasificación con códigos, claves foráneas para tablas de códigos o con banderas. El subtipo se usa para modelar conjuntos de predicados distintos para diferentes tipos de cosas de interés. Si usa subtipos simplemente para la clasificación, entonces es una mala práctica.

Si sus subtipos modelan clara e inequívocamente diferentes conjuntos de predicados para las cosas que le interesan a su base de datos, entonces es una práctica perfectamente buena, independientemente de cuántos subtipos necesite.

Joel Brown
fuente
Gracias, tenía miedo de ponerme una trampa. Mi problema es que cada uno de los subtipos tendrá muchas columnas. Algunos se superpondrán y los pondré en una cartabla, pero muchos no lo harán y se colocarán en una tabla de subtipos. Por ejemplo, será algo así como almacenar partes elementales de tipos de automóviles. El motor de un automóvil eléctrico puede tener 100 partes, un motor de gasolina 75 partes y un híbrido de 125 partes. 50 partes serían comunes y se almacena en cars, mientras que el 50, 25 y 75 estarán en electric_car, gas_cary hybrid_carmesas
Arthur Tarasov