Cómo diseñar una tabla de productos para muchos tipos de productos donde cada producto tiene muchos parámetros


No tengo mucha experiencia en el diseño de mesas. Mi objetivo es crear una o más tablas de productos que cumplan con los siguientes requisitos:

  • Soporta muchos tipos de productos (TV, Teléfono, PC,...). Cada tipo de producto tiene un conjunto diferente de parámetros, como:

    • El teléfono tendrá Color, Tamaño, Peso, Sistema operativo...

    • PC tendrá CPU, HDD, RAM...

  • El conjunto de parámetros debe ser dinámico. Puede agregar o editar cualquier parámetro que te gusta.

¿Cómo puedo cumplir estos requisitos sin una tabla separada para cada tipo de producto?

Author: Air, 2009-03-30

4 answers

Tiene al menos estas cinco opciones para modelar la jerarquía de tipos que describe:

  • Herencia de tabla única : una tabla para todos los tipos de productos, con suficientes columnas para almacenar todos los atributos de todos los tipos. Esto significa un montón de columnas, la mayoría de las cuales son NULL en cualquier fila dada.

  • Class Table Inheritance : una tabla para Productos, que almacena atributos comunes a todos los tipos de productos. Luego una tabla por tipo de producto, almacenando atributos específicos de ese tipo de producto.

  • Herencia de tabla de concreto : no hay tabla para atributos de productos comunes. En su lugar, una tabla por tipo de producto, que almacena tanto los atributos comunes del producto como los atributos específicos del producto.

  • LOB serializado : Una tabla para Productos, que almacena atributos comunes a todos los tipos de productos. Una columna adicional almacena un BLOB de datos semiestructurados, en XML, YAML, JSON o algún otro formato. Este BLOB le permite almacene los atributos específicos de cada tipo de producto. Puede utilizar patrones de diseño de lujo para describir esto, como Fachada y Memento. Pero a pesar de todo, tiene un blob de atributos que no se pueden consultar fácilmente dentro de SQL; tiene que recuperar todo el blob a la aplicación y ordenarlo allí.

  • Entity-Attribute-Value : Una tabla para Productos y una tabla que pivota atributos a filas, en lugar de columnas. EAV no es un diseño válido con respecto a la paradigma relacional, pero mucha gente lo usa de todos modos. Este es el "Patrón de propiedades" mencionado por otra respuesta. Vea otras preguntas con la etiqueta eav en StackOverflow para ver algunos de los escollos.

He escrito más sobre esto en una presentación, Extensible Data Modeling.


Pensamientos adicionales sobre EAV: Aunque muchas personas parecen estar a favor de EAV, yo no. Parece la solución más flexible, y por lo tanto la mejor. Sin embargo, mantener en mente el adagio TANSTAAFL . Estas son algunas de las desventajas de EAV:

  • No hay forma de hacer una columna obligatoria (equivalente a NOT NULL).
  • No hay forma de usar tipos de datos SQL para validar entradas.
  • No hay forma de asegurar que los nombres de atributos se escriban de manera consistente.
  • No hay manera de poner una clave foránea en los valores de cualquier atributo dado, por ejemplo, para una tabla de búsqueda.
  • Obtener resultados en un diseño tabular convencional es complejo y costoso, porque para obtener atributos de varias filas que necesita hacer JOIN para cada atributo.

El grado de flexibilidad que le da EAV requiere sacrificios en otras áreas, probablemente haciendo que su código sea tan complejo (o peor) de lo que habría sido para resolver el problema original de una manera más convencional.

Y en la mayoría de los casos, es innecesario tener ese grado de flexibilidad. En la pregunta del OP sobre los tipos de productos, es mucho más sencillo crear una tabla por tipo de producto para productos específicos atributos, por lo que tiene alguna estructura consistente aplicada al menos para las entradas del mismo tipo de producto.

Usaría EAV solo si se debe permitir que cada fila tenga potencialmente un conjunto distinto de atributos. Cuando tiene un conjunto finito de tipos de productos, EAV es excesivo. La herencia de la mesa de clase sería mi primera opción.

 194
Author: Bill Karwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:54

@StoneHeart

Me gustaría ir aquí con EAV y MVC todo el camino.

@ Bill Karvin

Estas son algunas de las desventajas de EAV:

No way to make a column mandatory (equivalent of NOT NULL).
No way to use SQL data types to validate entries.
No way to ensure that attribute names are spelled consistently.
No way to put a foreign key on the values of any given attribute, e.g.

Para una tabla de búsqueda.

Todas esas cosas que has mencionado aquí:

  • validación de datos
  • nombres de atributos validación de ortografía
  • columnas/campos obligatorios
  • manejo de la destrucción de atributos dependientes

En mi opinión no pertenecen en una base de datos en absoluto porque ninguna de las bases de datos son capaces de manejar esas interacciones y requisitos en un nivel adecuado como lo hace un lenguaje de programación de una aplicación.

En mi opinión usar una base de datos de esta manera es como usar una roca para martillar un clavo. Puedes hacerlo con una roca, pero ¿no se supone que debes usar un martillo que sea más preciso y específicamente diseñado para este tipo de actividad ?

Obtener resultados en un diseño tabular convencional es complejo y caro, porque para obtener atributos de varias filas que necesita hacer UNIRSE para cada atributo.

Este problema se puede resolver haciendo pocas consultas sobre datos parciales y procesándolos en un diseño tabular con su aplicación. Incluso si tiene 600 GB de datos de productos, puede procesarlos en lotes si necesita datos de cada fila de esta tabla.

Yendo más allá Si desea mejorar el rendimiento de las consultas puede seleccionar ciertas operaciones como por ejemplo, para informes o búsqueda de texto global y preparar para ellos tablas de índices que almacenarían los datos requeridos y se regenerarían periódicamente, digamos cada 30 minutos.

Ni siquiera necesita preocuparse por el costo del almacenamiento de datos adicional porque se vuelve más y más barato todos los días.

Si todavía le preocupa el rendimiento de las operaciones realizadas por la aplicación, siempre puede usar Erlang, C++, Go Language para preprocesar los datos y luego solo procesar los datos optimizados aún más en su aplicación principal.

 13
Author: Pawel Barcik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-07 16:37:23

Si utilizo Class Table Inheritance significa:

Una tabla para los Productos, almacenando atributos comunes a todos los tipos de productos. Luego, una tabla por tipo de producto, almacenando atributos específicos para ese tipo de producto. - Bill Karwin

Que me gusta lo mejor de las Sugerencias de Bill Karwin.. Puedo prever un inconveniente, que trataré de explicar cómo evitar que se convierta en un problema.

¿Qué plan de contingencia debo tener en su lugar cuando un atributo que es solo común a 1 tipo, entonces se convierte en común a 2, entonces 3, etc?

Por ejemplo: (esto es solo un ejemplo, no es mi problema real)

Si vendemos muebles, podríamos vender sillas, lámparas, sofás, Televisores, etc. El tipo de TV podría ser el único tipo que llevamos que tiene un consumo de energía. Así que pondría el atributo power_consumption en el tv_type_table. Pero entonces empezamos a llevar sistemas de cine en casa que también tienen una propiedad power_consumption. OK es solo otro producto, así que agregaré este campo a stereo_type_table también ya que eso es probablemente más fácil en este punto. Pero con el tiempo, a medida que empezamos a llevar más y más electrónica, nos damos cuenta de que power_consumption es lo suficientemente amplio como para que debería estar en el main_product_table. ¿Qué debo hacer ahora?

Añadir el campo a la main_product_table. Escriba un script para recorrer la electrónica y poner el valor correcto de cada type_table al main_product_table. Luego suelte esa columna de cada type_table.

Ahora si yo siempre estaba usando la misma clase GetProductData para interactuar con la base de datos para extraer el producto info; entonces, si cualquier cambio en el código ahora necesita refactorización, debería ser solo para esa Clase.

 5
Author: JD Isaacks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-16 19:31:34

Puede tener una tabla de productos y una tabla ProductAdditionInfo separada con 3 columnas: ID de producto, nombre de información adicional, valor de información adicional. Si el color es utilizado por muchos pero no todos los tipos de Productos, podría ser una columna anulable en la tabla de productos, o simplemente ponerlo en ProductAdditionalInfo.

Este enfoque no es una técnica tradicional para una base de datos relacional, pero he visto que se usa mucho en la práctica. Puede ser flexible y tener un buen rendimiento.

Steve Yegge llama a esto el patrón de propiedades y escribió un largo post sobre su uso.

 3
Author: RossFabricant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-30 01:44:33