Estoy desarrollando una herramienta que maneja piezas (eléctricas). Las partes se pueden crear, ver, modificar, eliminar, agrupar, etc.
Para que esta pregunta sea útil para futuros visitantes, me gusta mantener esta pregunta universal ya que administrar partes en un DB es muy común, sin importar qué partes estén en el DB (CD, autos, comida, estudiantes, ...).
Estoy pensando en 3 diseños diferentes de DB:
Usar una tabla de partes y tablas derivadas para atributos de parte especializados.
Parts (id, part_type_id, name) PartTypes (id, name) Wires (id, part_id, lenght, diameter, material) Contacts (id, part_id, description, picture)
Utilizando solo tablas de piezas especializadas.
Wires (id, name, lenght, diameter, material) Contacts (id, name, description, picture)
Usando una tabla Parts-, PartTypes-, ValueTypes- y PartValues que contiene todos los valores.
PartTypes (id, name) ValueTypes (id, part_type_id, name) Parts (id, part_type_id, name) PartValues (part_id, value_type_id, value)
¿Cuál preferir y por qué? ¿O hay uno mejor?
Estoy preocupado por las consultas DB. No quiero que las consultas se vuelvan demasiado lentas o complicadas.
Actualizar
El número de tipos en la base de datos es bastante dado y estático, ya que se basa en un estándar internacional y rara vez se mejorará.
fuente
Respuestas:
Opción 3 : (a veces) La
opción 3 es el diseño "EAV" . En teoría es bueno porque los campos se sacan de la estructura de la tabla y se convierten en datos. Pero da un rendimiento terrible. También prohíbe el uso de una indexación adecuada. Y hace que las consultas sean mucho más complicadas.
Solo usaría EAV en circunstancias especiales. He usado EAV para calcular las piezas auxiliares necesarias para los pedidos y funcionó bien. Pero esté muy cansado de usarlo como diseño para sus tablas principales.
Opción 2 : (¿nunca?) La
opción 2 es un no no. ¿Qué pasa con los campos compartidos? ¿Va a duplicar la estructura de la tabla para cada campo compartido? Requeriría que incluya sindicatos en los informes de todo el sistema.
Opción 1 : (¡ganador!) La
opción 1 puede parecer un poco demasiado básica, pero probablemente sea la mejor apuesta para sus mesas principales. Todas las partes usan la misma tabla maestra para los campos compartidos, por lo que se evitan las uniones en sus informes. Tiene un gran rendimiento que permite el uso adecuado de la indexación. Las consultas son al estilo tradicional y son simples.
La desventaja de la opción 1 es que no puede agregar campos dinámicamente. ¿Pero realmente quieres? Al agregar campos dinámicamente, está realizando el diseño de la base de datos en tiempo de ejecución.
fuente
Tendería a no tener la opción # 3.
La opción n. ° 3 es la configuración del par nombre-valor que viola la normalización.
Idealmente, uno intenta tener algún nivel de normalización de la base de datos. Esforzarse por la normalización completa y luego desnormalizar según sea necesario cuando se identifica por problemas de personalización o rendimiento.
Considere la consulta "¿Cuál es el nombre y las ID de piezas para todos los cables de cobre"
La estructura n. ° 1 es
Estructura # 2 es
Estructura # 3 es
Considere también la complicación de las inserciones y eliminaciones del sistema.
Algunas lecturas adicionales sobre por qué no # 3 - La maldición del par de valores de nombre
fuente
part_type_id = part_types.id
yvalue_types.id = part_values.type_value_id
ambas son cláusulas de unión que dejan el lugar donde el tipo de parte es alambre, el tipo de valor es material y el valor es cobre que es relativamente sucintoVoy opción 3
La opción 1 es mala porque no desea que sus combinaciones se basen en un valor archivado. (es decir
If type ="Wire" join to TblWire
)La opción 2 es mala porque no tiene forma de informar sobre su inventario en su conjunto
fuente
Comenzaría con un modelo de datos / objetos que permite la herencia, y luego usaría un mapeo relacional de objetos estándar . De esta forma, obtienes una clase base
Parts
y subclases comoWires
,Contacts
etc. Ahora, si aplicas una estrategia de "asignar cada clase a la propia tabla", obtienes la opción 1, que es la solución más "normalizada" y debería ser la estrategia canónica si no tiene más información sobre las consultas que espera.La opción 2 es lo que obtienes al aplicar un enfoque de "mapa-cada-clase-concreta-a-propia-tabla". Esto puede evitar "uniones" y puede funcionar mejor para algún tipo si las consultas (especialmente consultas para un solo "tipo de parte"), por otro lado, hace que el manejo genérico con todas las partes sea más difícil y más lento. Evita esto si no tienes razones especiales para ello.
La opción 3 es lo que necesita solo si desea que el usuario cambie la cantidad de tipos de piezas en tiempo de ejecución; si no espera ese requisito, la opción 3 será un ejemplo perfecto para cosas de ingeniería excesiva.
fuente
Con la base de datos NOSQL DB (como MongoDB, por ejemplo) solo necesitará un conjunto llamado "Partes". Cada parte de ese conjunto se denomina documento - registro con un conjunto variable de campos:
Creo que este es el almacenamiento de datos más natural para la tarea que describe.
fuente
Definitivamente vaya con la opción 1 pero con algunas modificaciones muy simples:
Luego puede usar las restricciones CHECK y los valores DEFAULT para asegurarse de que part_type_id sea correcto, y luego puede unirse tanto en part_type_id como en part_id. Esto evita tener una unión condicional basada en una sola tabla, y si necesita agregar un part_type_id a los cables (digamos que estamos subdividiendo esa parte y agregando otra tabla de atributos extendidos), las restricciones predeterminadas y de verificación se pueden cambiar.
fuente
wires.id
ycontacts.id
ya que la(part_id, part_type_id)
combinación será suficiente para identificar de forma exclusiva una parte.La opción 3 es más genérica y puede acomodar más casos de uso.
Al ir a la opción 3, es posible que necesite más uniones y consultas complejas para funciones simples, en la opción 2 necesitaría consultas complejas para características "grandes" como inventario e informes, y es posible que necesite usar uniones para lograr eso.
Siempre puede simplificar sus consultas en las opciones 3 usando Vistas, si a menudo solo necesita el Cable o el Contacto, haga una Vista para cada uno de ellos. Puede optimizarlo si es necesario.
fuente