2010-05-26 14 views
16

Estamos comenzando un nuevo proyecto en el que tenemos que almacenar productos y muchos atributos de productos en una base de datos. La pila de tecnología es MS SQL 2008 y Entity Framework 4.0/LINQ para acceso a datos.Mejor patrón para almacenar atributos (producto) en SQL Server

Los productos (y la Tabla de productos) son bastante sencillos (un SKU, fabricante, precio, etc.). Sin embargo, también hay muchos atributos para almacenar con cada producto (piense en widgets industriales). Estos pueden variar desde el color hasta la (s) certificación (es) hasta el tamaño de la tubería. Cada producto puede tener diferentes atributos, y algunos pueden tener múltiplos del mismo atributo (Ej: Certificaciones).

La propuesta actual es que básicamente tendremos una tabla de pares de nombre/valor con un FK de vuelta a la identificación del producto en cada fila.

Un ejemplo de la tabla de atributos puede tener este aspecto:

ProdID  AttributeName  AttributeValue 
123  Color    Blue 
123  FittingSize  1.25 
123  Certification  AS1111 
123  Certification  EE2212 
123  Certification  FM.3 
456  Pipe    11 
678  Color    Red 
999  Certification  AE1111 
... 

Nota: Nombre de atributo es probable venir de una tabla de consulta o enumeración.

Así que la pregunta principal aquí es: ¿Es este el mejor patrón para hacer algo como esto? ¿Cómo será el rendimiento? Las consultas se basarán en un JOIN de la tabla de productos y atributos, y generalmente necesitan muchos WHERE para filtrar atributos específicos: la búsqueda más común será encontrar un producto basado en un conjunto de atributos conocidos/deseados.

Si alguien tiene alguna sugerencia o un patrón mejor para este tipo de datos, hágamelo saber.

Gracias! -Ed

Respuesta

15

Está a punto de reinventar el temido modelo de EAV, Entity-Attribute-Value. Esto es notorio por tener problemas en la vida real, por varias razones, muchas cubiertas por la respuesta de Dave.

Afortunadamente, el equipo de asesoramiento al cliente de SQL (SQLCAT) tiene un documento técnico sobre el tema, Best Practices for Semantic Data Modeling for Performance and Scalability. Recomiendo este artículo. Desafortunadamente, no ofrece una panacea, una solución cortadora de galletas, ya que el problema no tiene solución. En su lugar, usted aprenderá cómo encontrar el equilibrio entre un esquema consultable fija y una estructura flexible de EAV, un equilibrio que funciona para su caso específico:

modelos de datos semánticos pueden ser muy complejas y hasta bases de datos semánticas están comúnmente disponibles, el desafío permanece para encontrar el equilibrio óptimo entre el modelo de objeto puro y el modelo relacional puro para cada aplicación . La clave del éxito es comprender los problemas, realizar las medidas necesarias para esos problemas , y luego probar, probar y probar. La prueba de escalabilidad es un factor de éxito crítico si va a para encontrar ese diseño óptimo.

+1

+1, solo porque el papel vinculado es más útil que cualquier cosa escrita en esta página hasta el momento. –

+0

Este documento ayudó, y nos dio bastante para pensar. ¡Gracias! – EdH

13

Esto va a ser problemático para un par de razones:

  • Sus consultas de entidad será mucho más difícil de escribir. Transformar los resultados de esas consultas en algo parecido a un ViewModel cuando llega el momento de la presentación va a ser doloroso porque implicará un pivote para cada producto.

  • Entender cuáles serán sus tipos de datos va a ser difícil cuando llega el momento de leer ciertos tipos de datos. ¿Estás planeando almacenar esto como cadenas? Por ejemplo, DateTimes contiene más datos que la implementación predeterminada .ToString() escribe en la cadena. También tendrá problemas si intenta almacenar valores de coma flotante.

  • La integridad de los datos de sus objetos está en riesgo. Habrá una tentación de poner propiedades que deberían ser solo atributos de las tablas de productos principales en este "cubo de datos". Tal vez el diseño sea semi-cuerdo para empezar, pero te garantizo que después de un cierto período de tiempo, la gente comenzará a arrojar propiedades en la bolsa. Entonces será muy difícil mantener la integridad de tus objetos con una estructura tan vagamente definida.

  • Es probable que sus índices no sean óptimos. Nuevamente piense en una propiedad que debería estar en su tabla de productos. En lugar de poder indexar en una sola columna, ahora se verá obligado a crear un índice compuesto potencialmente muy grande en su tabla de "tipo".

  • Dado que al parecer planea tirar los tipos de datos adecuados y utilizar cadenas, es probable que el rendimiento de las consultas de rango para datos numéricos sea pobre.

  • Su tabla obtendrá grandes, ralentizando copias de seguridad y consultas.En lugar de un entero de 4 bytes, tendrá que almacenar mucho más para un entero de cualquier tamaño.

Mejor para normalizar la tabla de una manera más "tradicional" con relaciones "IS-A". Por ejemplo, puede tener tubos, que son un tipo de producto, pero tienen un par de atributos más. Es posible que tenga estufas, que son un tipo de producto, pero todavía tienen un par de atributos.

Si realmente tiene una base de datos genérica y todo tipo de otras propiedades que no van a estar sujetas a reglas de integridad de datos, puede que desee considerar almacenar datos en una columna XML. Es difícil decirle cuál es la opción correcta de diseño a menos que sepa mucho más sobre su negocio.

IMO esto es un antipatrón de diseño. La canción de la sirena de esta idea ha atraído a muchos desarrolladores a las rocas de una aplicación que no se puede mantener.

+0

Gracias por pasar el tiempo para dejar una respuesta detallada. Estamos de acuerdo en que hay muchos problemas con este plan, pero la (semi) solución que usted propuso tampoco ayudará. Puede haber cientos de atributos para un solo SKU. Las certificaciones y otros atributos entran y salen mensualmente. No estoy seguro de cómo alguna vez podríamos gestionar este esquema con las relaciones IS-A tradicionales. Necesitaríamos varias personas dedicadas a esta aplicación/esquema solo para administrar los cambios de SKU semanalmente. – EdH

+1

Es por eso que debería considerar usar la columna XML. PUEDE usar EAV en su base de datos para algunos atributos, solo que no espere que la búsqueda y los informes sean rápidos o intuitivos. Realmente necesita comprender cómo/si se van a buscar estos atributos, y cómo cada atributo puede aparecer y desaparecer en el ciclo de vida de la aplicación.Este análisis empresarial esencial le dirá a dónde pertenece cada atributo. –

1

En lugar de tener una tabla de nombre-valor, cree la estructura habitual de la tabla Producto que contenga todos los atributos comunes y agregue una columna XML para los atributos que varían según el producto.

He usado esta estructura antes y funcionó bastante bien.

Como menciona @Dave Markle, el enfoque del valor de los nombres puede llevar a un mundo de dolor.

+0

¿Qué tan eficiente será interrogar contra ese XML por atributos específicos? – EdH

+1

Si crea juiciosamente índices xml, el rendimiento estará bien. –

2

En resumen, no se puede recorrer una sola ruta. Si usa un EAV como su ejemplo, tendrá una miríada de problemas como los delineados por los otros carteles, entre los cuales el rendimiento y la integridad de los datos. Permítanme reiterar que el uso de un EAV como núcleo de su solución fallará cuando llegue el momento de informar y analizar. Sin embargo, como también ha declarado, es posible que tenga cientos de atributos que cambian regularmente.

La solución, IMO, es un híbrido. Para atributos comunes, use columnas/esquema estándar. Para atributos arbitrarios adicionales, use un EAV. Sin embargo, la regla con los datos EAV es que nunca, nunca, bajo ninguna circunstancia, puede escribir una consulta que incluya una clasificación o un filtro en un atributo. Es decir, nunca puede escribir Where AttributeName = 'Foo'.La parte EAV del esquema representa una bolsa de datos que simplemente está ahí para fines de seguimiento. De hecho, he visto a mucha gente implementar esta solución al usar Xml para la porción de EAV. En el momento en que alguien desea buscar, filtrar, ordenar o colocar un valor de EAV en un lugar específico en un informe, ese atributo debe elevarse a una columna de nivel superior en la tabla de productos.

La clave de este enfoque híbrido es la disciplina. Parecerá lo suficientemente simple agregar un filtro, ordenar o poner un atributo en un lugar específico en algún lugar de un informe, especialmente cuando la administración lo presiona. Debes resistir esta tentación. Una vez que avanzas por el camino oscuro ... Si no crees que puedes mantener ese nivel de disciplina en tu equipo de desarrollo, entonces no usaría un EAV. Como he mencionado antes, los EAV son como las drogas: en pequeñas cantidades y utilizados en las circunstancias adecuadas, pueden ser beneficiosos. Demasiado te matará.

4

Sé que es muy antigua - sin embargo, puede haber otros lectores ...

he visto la EAV equilibrio atribuir enfoque de modelado. Bueno, todavía es EAV. "Los EAV son como las drogas" es más o menos cierto. Entonces, ¿qué tal si lo pensamos una vez más? Y seamos realmente agresivos: Aún me gusta el supertipo apporach, donde muchas tablas usan la misma clave primaria de un generador de claves. Reutilicemos este. Entonces, ¿qué hay de crear una nueva tabla para cada conjunto de atributos, todos tienen el primario del mismo generador de claves? P.ej. Tendría una tabla con los campos "color, tubería", otra tabla "tamaño de accesorio, tubería", y así sucesivamente. El requisito "volatilidad de los atributos" exige un diccionario de datos cuidadosamente mantenido (de forma automática) de todos modos.

Este enfoque está completamente normalizado y se puede automatizar por completo. Puede admitir comprobaciones si los conjuntos de atributos específicos se han materializado ya como tabla mediante agrupaciones de nombres de atributos hash, por ejemplo. crc32 (lower ('color ~ fittingsize ~ pipe')) donde los nombres de los atributos deben ordenarse alfabéticamente. Por supuesto, esto requiere tener el hash en el diccionario de datos. Basado en el diccionario de datos, cada objeto puede ser buscado (usando 'UNION'), especialmente si el diccionario de datos en sí es una tabla. Tener el diccionario de datos como tabla también le permite usar su clave primaria (sustituta) como base para nombres de tabla únicos, para terminar con tablas como 'attributes1', 'attributes2', ... La mayoría de las bases de datos soportan actualmente miles de millones de tablas, así que son una especie de ahorrar en ese extremo también. Incluso podría tener un catálogo de productos con atributos muy comunes, que hacen referencia a las tablas de atributos extendidos.

Un problema abierto son 1: n conjuntos de datos. Me temo que debes ordenarlos en tablas separadas. Sin embargo, esto depende mucho de su presentación de datos y estrategia de consulta. ¿Deberían presentarse siempre como una secuencia separada por comas adjunta al producto o desea, por ejemplo? ser capaz de consultar todos los productos de una determinada certificación?

Antes de iniciar este enfoque, tenga en cuenta lo siguiente: Es para casos de uso en los que tiene una volatilidad muy alta de atributos, en cantidad y calidad solamente. También está predefinido que no puede conocer la mayoría de los atributos en el momento en que se crea la solución. Por lo tanto, no discuta esto en un contexto en el que pueda modelar sus atributos por adelantado, lo que le permitiría equilibrar las compensaciones mucho mejor.

Cuestiones relacionadas